From 0febcf69f4be7a53429b6c42225f47164b54fd2b Mon Sep 17 00:00:00 2001 From: yuancheng Date: Sun, 19 Jul 2026 18:27:27 +0800 Subject: [PATCH] main --- admin/admin.php | 209 +-- admin/change_password_required.php | 266 --- admin/config | 1 - admin/config/browserdetect.php | 15 + admin/config/config.php | 27 + admin/config/index.php | 0 admin/config/ircddbgateway_languages.inc | 24 + admin/config/ircddblocal.php | 15 + admin/config/language.php | 5 + admin/config/version.php | 3 + admin/config_backup.php | 716 ++------ admin/css | 1 - admin/css/index.php | 0 admin/css/ircddb.css | 328 ++++ admin/css/mini_ircddb.css | 330 ++++ admin/css/nice-select.min.css | 1 + admin/css/pistar-css-mini.php | 915 ++++++++++ admin/css/pistar-css.php | 1104 ++++++++++++ admin/download_modem_log.php | 95 +- admin/dstarrepeater | 1 - .../dstarrepeater/active_reflector_links.php | 187 +++ admin/dstarrepeater/active_starnet_groups.php | 125 ++ admin/dstarrepeater/css_connections.php | 76 + .../dstarrepeater/gateway_software_config.php | 20 + admin/dstarrepeater/index.php | 0 admin/dstarrepeater/last_herd.php | 91 + admin/dstarrepeater/link_manager.php | 205 +++ admin/dstarrepeater/local_tx.php | 89 + admin/dstarrepeater/system.php | 56 + admin/expert/edit_dapnetgateway.php | 172 +- admin/expert/edit_dashboard.php | 330 ++-- admin/expert/edit_dmrgateway.php | 188 +-- admin/expert/edit_dstarrepeater.php | 167 +- admin/expert/edit_ircddbgateway.php | 193 +-- admin/expert/edit_mmdvmhost.php | 235 +-- admin/expert/edit_nxdngateway.php | 174 +- admin/expert/edit_p25gateway.php | 172 +- admin/expert/edit_starnetserver.php | 164 +- admin/expert/edit_timeserver.php | 164 +- admin/expert/edit_ysfgateway.php | 174 +- admin/expert/fulledit_bmapikey.php | 194 +-- admin/expert/fulledit_cron.php | 366 +--- admin/expert/fulledit_dapnetapi.php | 194 +-- admin/expert/fulledit_dmrgateway.php | 93 +- admin/expert/fulledit_pistar-remote.php | 96 +- admin/expert/fulledit_rssidat.php | 86 +- admin/expert/fulledit_wpaconfig.php | 94 +- admin/expert/index.php | 60 +- admin/expert/jitter_test.php | 44 +- admin/expert/modem_fw_upgrade.php | 165 +- admin/expert/ssh_access.php | 76 +- admin/expert/upgrade.php | 138 +- admin/images | 1 - admin/images/20green.png | Bin 0 -> 1247 bytes admin/images/20red.png | Bin 0 -> 1207 bytes admin/images/download.png | Bin 0 -> 12380 bytes admin/images/favicon.ico | Bin 0 -> 1150 bytes admin/images/index.php | 0 admin/images/reboot.png | Bin 0 -> 34314 bytes admin/images/restore.png | Bin 0 -> 13801 bytes admin/images/shutdown.png | Bin 0 -> 22498 bytes admin/index.php | 331 +++- admin/lang | 1 - admin/lang/catalan_es.php | 158 ++ admin/lang/chinese_cn.php | 157 ++ admin/lang/chinese_hk.php | 157 ++ admin/lang/chinese_tw.php | 155 ++ admin/lang/dutch_nl.php | 156 ++ admin/lang/english_uk.php | 157 ++ admin/lang/english_us.php | 157 ++ admin/lang/french_fr.php | 157 ++ admin/lang/german_de.php | 157 ++ admin/lang/greek_gr.php | 157 ++ admin/lang/hungarian_hu.php | 157 ++ admin/lang/index.php | 1 + admin/lang/italian_it.php | 157 ++ admin/lang/japanese_jp.php | 159 ++ admin/lang/norwegian_no.php | 157 ++ admin/lang/polish_pl.php | 157 ++ admin/lang/portuguese_br.php | 157 ++ admin/lang/portuguese_pt.php | 158 ++ admin/lang/romanian_ro.php | 157 ++ admin/lang/slovenian_sl.php | 157 ++ admin/lang/spanish_es.php | 157 ++ admin/lang/spanish_mx.php | 157 ++ admin/lang/swedish_se.php | 158 ++ admin/lang/thai_th.php | 157 ++ admin/lang/turkish_tr.php | 157 ++ admin/live_modem_log.php | 55 +- admin/mmdvmhost | 1 - admin/mmdvmhost/bm_links.php | 113 ++ admin/mmdvmhost/bm_manager.php | 137 ++ admin/mmdvmhost/functions.php | 1480 +++++++++++++++++ admin/mmdvmhost/index.php | 0 admin/mmdvmhost/lh.php | 201 +++ admin/mmdvmhost/localtx.php | 108 ++ admin/mmdvmhost/m17_manager.php | 142 ++ admin/mmdvmhost/nxdn_manager.php | 114 ++ admin/mmdvmhost/p25_manager.php | 115 ++ admin/mmdvmhost/pages.php | 137 ++ admin/mmdvmhost/repeaterinfo.php | 413 +++++ admin/mmdvmhost/tgif_links.php | 96 ++ admin/mmdvmhost/tgif_manager.php | 165 ++ admin/mmdvmhost/tools.php | 93 ++ admin/mmdvmhost/ysf_manager.php | 139 ++ admin/pistar-keeper-download.php | 16 +- admin/power.php | 115 +- admin/sysinfo.php | 117 +- admin/update.php | 201 +-- admin/wifi/index.php | 3 - admin/wifi/phpincs.php | 358 ++-- admin/wifi/styles.php | 210 ++- api/last_heard.php | 64 +- config/banner_warnings.inc | 427 ----- config/browserdetect.php | 42 +- config/config.php | 73 +- config/config_writer.php | 570 ------- config/csrf.php | 426 ----- config/ircddblocal.php | 37 +- config/security_headers.php | 193 --- config/version.php | 10 +- css/index.php | 3 - css/pistar-css-mini.php | 758 +++++++-- css/pistar-css.php | 940 +++++++++-- dstarrepeater/active_reflector_links.php | 194 +-- dstarrepeater/active_starnet_groups.php | 184 +- dstarrepeater/css_connections.php | 67 +- dstarrepeater/gateway_software_config.php | 4 +- dstarrepeater/last_herd.php | 99 +- dstarrepeater/link_manager.php | 242 ++- dstarrepeater/local_tx.php | 86 +- dstarrepeater/system.php | 37 +- lang/catalan_es.php | 297 ++-- lang/chinese_cn.php | 297 ++-- lang/chinese_hk.php | 297 ++-- lang/chinese_tw.php | 295 ++-- lang/dutch_nl.php | 297 ++-- lang/english_uk.php | 297 ++-- lang/english_us.php | 297 ++-- lang/french_fr.php | 297 ++-- lang/german_de.php | 299 ++-- lang/greek_gr.php | 297 ++-- lang/hungarian_hu.php | 297 ++-- lang/index.php | 4 +- lang/italian_it.php | 297 ++-- lang/japanese_jp.php | 297 ++-- lang/norwegian_no.php | 297 ++-- lang/polish_pl.php | 299 ++-- lang/portuguese_br.php | 297 ++-- lang/portuguese_pt.php | 298 ++-- lang/romanian_ro.php | 297 ++-- lang/slovenian_sl.php | 297 ++-- lang/spanish_es.php | 297 ++-- lang/spanish_mx.php | 297 ++-- lang/swedish_se.php | 297 ++-- lang/thai_th.php | 297 ++-- lang/turkish_tr.php | 297 ++-- mmdvmhost/bm_links.php | 77 +- mmdvmhost/bm_manager.php | 29 +- mmdvmhost/index.php | 3 - mmdvmhost/localtx.php | 169 +- mmdvmhost/m17_manager.php | 298 ++-- mmdvmhost/nxdn_manager.php | 240 ++- mmdvmhost/p25_manager.php | 243 ++- mmdvmhost/pages.php | 42 +- mmdvmhost/repeaterinfo.php | 515 +++--- mmdvmhost/tgif_links.php | 96 ++ mmdvmhost/tgif_manager.php | 339 ++-- mmdvmhost/tools.php | 156 +- mmdvmhost/ysf_manager.php | 293 ++-- 170 files changed, 19490 insertions(+), 11878 deletions(-) delete mode 100644 admin/change_password_required.php delete mode 100644 admin/config create mode 100644 admin/config/browserdetect.php create mode 100644 admin/config/config.php create mode 100644 admin/config/index.php create mode 100644 admin/config/ircddbgateway_languages.inc create mode 100644 admin/config/ircddblocal.php create mode 100644 admin/config/language.php create mode 100644 admin/config/version.php delete mode 100644 admin/css create mode 100644 admin/css/index.php create mode 100644 admin/css/ircddb.css create mode 100644 admin/css/mini_ircddb.css create mode 100644 admin/css/nice-select.min.css create mode 100644 admin/css/pistar-css-mini.php create mode 100644 admin/css/pistar-css.php delete mode 100644 admin/dstarrepeater create mode 100644 admin/dstarrepeater/active_reflector_links.php create mode 100644 admin/dstarrepeater/active_starnet_groups.php create mode 100644 admin/dstarrepeater/css_connections.php create mode 100644 admin/dstarrepeater/gateway_software_config.php create mode 100644 admin/dstarrepeater/index.php create mode 100644 admin/dstarrepeater/last_herd.php create mode 100644 admin/dstarrepeater/link_manager.php create mode 100644 admin/dstarrepeater/local_tx.php create mode 100644 admin/dstarrepeater/system.php delete mode 100644 admin/images create mode 100644 admin/images/20green.png create mode 100644 admin/images/20red.png create mode 100644 admin/images/download.png create mode 100644 admin/images/favicon.ico create mode 100644 admin/images/index.php create mode 100644 admin/images/reboot.png create mode 100644 admin/images/restore.png create mode 100644 admin/images/shutdown.png delete mode 100644 admin/lang create mode 100644 admin/lang/catalan_es.php create mode 100644 admin/lang/chinese_cn.php create mode 100644 admin/lang/chinese_hk.php create mode 100644 admin/lang/chinese_tw.php create mode 100644 admin/lang/dutch_nl.php create mode 100644 admin/lang/english_uk.php create mode 100644 admin/lang/english_us.php create mode 100644 admin/lang/french_fr.php create mode 100644 admin/lang/german_de.php create mode 100644 admin/lang/greek_gr.php create mode 100644 admin/lang/hungarian_hu.php create mode 100644 admin/lang/index.php create mode 100644 admin/lang/italian_it.php create mode 100644 admin/lang/japanese_jp.php create mode 100644 admin/lang/norwegian_no.php create mode 100644 admin/lang/polish_pl.php create mode 100644 admin/lang/portuguese_br.php create mode 100644 admin/lang/portuguese_pt.php create mode 100644 admin/lang/romanian_ro.php create mode 100644 admin/lang/slovenian_sl.php create mode 100644 admin/lang/spanish_es.php create mode 100644 admin/lang/spanish_mx.php create mode 100644 admin/lang/swedish_se.php create mode 100644 admin/lang/thai_th.php create mode 100644 admin/lang/turkish_tr.php delete mode 100644 admin/mmdvmhost create mode 100644 admin/mmdvmhost/bm_links.php create mode 100644 admin/mmdvmhost/bm_manager.php create mode 100644 admin/mmdvmhost/functions.php create mode 100644 admin/mmdvmhost/index.php create mode 100644 admin/mmdvmhost/lh.php create mode 100644 admin/mmdvmhost/localtx.php create mode 100644 admin/mmdvmhost/m17_manager.php create mode 100644 admin/mmdvmhost/nxdn_manager.php create mode 100644 admin/mmdvmhost/p25_manager.php create mode 100644 admin/mmdvmhost/pages.php create mode 100644 admin/mmdvmhost/repeaterinfo.php create mode 100644 admin/mmdvmhost/tgif_links.php create mode 100644 admin/mmdvmhost/tgif_manager.php create mode 100644 admin/mmdvmhost/tools.php create mode 100644 admin/mmdvmhost/ysf_manager.php delete mode 100644 config/banner_warnings.inc delete mode 100644 config/config_writer.php delete mode 100644 config/csrf.php delete mode 100644 config/security_headers.php create mode 100644 mmdvmhost/tgif_links.php diff --git a/admin/admin.php b/admin/admin.php index d191786..9794e4c 100644 --- a/admin/admin.php +++ b/admin/admin.php @@ -1,43 +1,3 @@ -" link never ""` - * (or `unlink`) against the running ircDDBGateway. - * - * Hit directly via /admin/admin.php (the form action self-posts); - * not inline-included by any current parent page. The historical - * "Loaded inline by /admin/index.php" docstring claim was stale — - * there is no `include 'admin.php'` site in the codebase today. - * Reachable only by direct navigation; admin/configure.php - * configures the *password* for the same `remotecontrold` daemon - * but doesn't issue link/unlink commands. - * - * Service-status row pgreps for the six daemons (DStarRepeater, - * MMDVMHost, ircDDBgateway, timeserver, pistar-watchdog, - * pistar-keeper) and renders a green/red dot per service. - * - * Input validation: preg_match whitelist on Module / RefName / - * Letter / Link verb (uppercase A-Z and digits only). That guards - * against shell-quote escape but does not substitute for CSRF — - * a forged POST with valid-looking values could otherwise trigger - * link/unlink under the operator's basic-auth session. csrf_verify() - * below closes that gap before any sudo runs. - */ - -require_once($_SERVER['DOCUMENT_ROOT'] . '/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'] . '/config/csrf.php'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships and csrf_field() at line ~98 has a token to -// emit) and rejects forged POSTs cleanly with 403 before the -// `sudo remotecontrold "" link|unlink ...` state-change -// in the POST handler runs. -csrf_verify(); - -?> Service Status @@ -60,29 +20,21 @@ csrf_verify();
Reflector Connector\n"; - echo "
\n\n\n
Command OutputCommand Output
"; - // remotecontrold output is text from the daemon; escape on - // display defence-in-depth (the input fields above were - // already preg_match-whitelist-validated). - echo htmlspecialchars((string)exec($linkCommand), ENT_QUOTES, 'UTF-8'); - echo "
\n"; - } - if (($_POST["Link"] ?? '') == "UNLINK") { - echo "Reflector Connector\n"; - echo "\n\n\n
Command OutputCommand Output
"; - echo htmlspecialchars((string)exec($unlinkCommand), ENT_QUOTES, 'UTF-8'); - echo "
\n"; - } - } + if ($_POST["Link"] == "LINK") { + echo "Reflector Connector\n"; + echo "\n\n\n
Command OutputCommand Output
"; + echo exec($linkCommand); + echo "
\n"; + } + if ($_POST["Link"] == "UNLINK") { + echo "Reflector Connector\n"; + echo "\n\n\n
Command OutputCommand Output
"; + echo exec($unlinkCommand); + echo "
\n"; + } + } unset($_POST); echo ''; @@ -117,7 +66,6 @@ echo ' -Pi-Star — Change Default Password - - - -
-
-

Pi-Star — Default Password Change Required

-
-
- - - - -
Working...
Password changed. Your browser will re-prompt for the new credentials shortly.
- - -

You are connecting from outside the local network and your dashboard is still using the - factory default password. Set a new password to continue.

-Passwords do not match. Please enter the same value in both fields.'; - break; - case 'default': - $msg = 'Password rejected. The new password must be different from the factory default.'; - break; - case 'pam': - $msg = 'Password rejected by the system. It must satisfy the system password-quality rules (length, complexity, history).'; - break; - case 'invalid': - default: - $msg = 'Password rejected. It must not contain NUL / CR / LF bytes and must be at most 256 bytes long.'; - break; - } -?> -

- -
- - - - - - - - - - - - - -
- -
- -
- - -
-
- -
- -
- - diff --git a/admin/config b/admin/config deleted file mode 100644 index 4088526..0000000 --- a/admin/config +++ /dev/null @@ -1 +0,0 @@ -../config/ \ No newline at end of file diff --git a/admin/config/browserdetect.php b/admin/config/browserdetect.php new file mode 100644 index 0000000..0a3564a --- /dev/null +++ b/admin/config/browserdetect.php @@ -0,0 +1,15 @@ +\n"; + print " \n"; +} else { + $useragent=$_SERVER['HTTP_USER_AGENT']; + if (preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))) { + print " \n"; + print " \n"; + } else { + print " \n"; + print " \n"; + } +} +?> diff --git a/admin/config/config.php b/admin/config/config.php new file mode 100644 index 0000000..6fdbeee --- /dev/null +++ b/admin/config/config.php @@ -0,0 +1,27 @@ + diff --git a/admin/config/index.php b/admin/config/index.php new file mode 100644 index 0000000..e69de29 diff --git a/admin/config/ircddbgateway_languages.inc b/admin/config/ircddbgateway_languages.inc new file mode 100644 index 0000000..fabd552 --- /dev/null +++ b/admin/config/ircddbgateway_languages.inc @@ -0,0 +1,24 @@ +# ircddbgateway_languages.inc +# +# Written for Pi-Star Digital Voice by Andy Taylor (MW0MWZ) +# Orrigional request by Dennis Bonesky +# +# Updated 28-May-2017 +# +########################################################### +#language;ircddbgateway;timeserver +########################################################### +English_(UK);0;0 +Deutsch;1;4 +Dansk;2;0 +Francais;3;6 +Italiano;4;0 +Polski;5;0 +English_(US);6;2 +Espanol;7;9 +Svenska;8;8 +Nederlands_(NL);9;7 +Nederlands_(BE);10;7 +Norsk;11;10 +Portugues;12;11 +########################################################### diff --git a/admin/config/ircddblocal.php b/admin/config/ircddblocal.php new file mode 100644 index 0000000..4d9d682 --- /dev/null +++ b/admin/config/ircddblocal.php @@ -0,0 +1,15 @@ + + diff --git a/admin/config/language.php b/admin/config/language.php new file mode 100644 index 0000000..87e215a --- /dev/null +++ b/admin/config/language.php @@ -0,0 +1,5 @@ + diff --git a/admin/config/version.php b/admin/config/version.php new file mode 100644 index 0000000..3c7d415 --- /dev/null +++ b/admin/config/version.php @@ -0,0 +1,3 @@ + diff --git a/admin/config_backup.php b/admin/config_backup.php index 9c85dc4..0e65c00 100644 --- a/admin/config_backup.php +++ b/admin/config_backup.php @@ -1,143 +1,4 @@ - * basename => [path, mode, owner, group] - */ -function backup_files() -{ - // Each entry is [path, mode, owner, group]. The mode/owner/group - // tuple is what the restore loop passes to `sudo install -m -o - // -g`, and MUST match the corresponding /etc/sudoers.d/pistar- - // dashboard PISTAR_DASH_INSTALL line for that destination — or - // sudo will reject the install and the file will silently fail - // to restore. Pre-2026-05-01 the restore loop used a hardcoded - // `install -m 644 -o root -g root` for every entry, which - // worked under the old NOPASSWD: ALL sudoers but breaks under - // the path-scoped allowlist for: the .key files (require 600 - // www-data:www-data so the dashboard's per-page sudo-less - // parse_ini_file() reads still work — see fulledit_bmapikey.php - // for the full rationale), wpa_supplicant.conf (600 root:root), - // and the three system files (dhcpcd.conf, hosts, hostname) - // which have no install entry in the deployed sudoers at all - // and rely on a re-spun image to gain them. - return array( - // Network / WiFi - 'dhcpcd.conf' => array('/etc/dhcpcd.conf', 644, 'root', 'root'), - 'wpa_supplicant.conf' => array('/etc/wpa_supplicant/wpa_supplicant.conf', 600, 'root', 'root'), - // Gateway daemon configs (flat key=value INI-ish) - 'ircddbgateway' => array('/etc/ircddbgateway', 644, 'root', 'root'), - 'mmdvmhost' => array('/etc/mmdvmhost', 644, 'root', 'root'), - 'dstarrepeater' => array('/etc/dstarrepeater', 644, 'root', 'root'), - 'dapnetgateway' => array('/etc/dapnetgateway', 644, 'root', 'root'), - 'p25gateway' => array('/etc/p25gateway', 644, 'root', 'root'), - 'm17gateway' => array('/etc/m17gateway', 644, 'root', 'root'), - 'ysfgateway' => array('/etc/ysfgateway', 644, 'root', 'root'), - 'ysf2dmr' => array('/etc/ysf2dmr', 644, 'root', 'root'), - 'dgidgateway' => array('/etc/dgidgateway', 644, 'root', 'root'), - 'nxdngateway' => array('/etc/nxdngateway', 644, 'root', 'root'), - 'dmrgateway' => array('/etc/dmrgateway', 644, 'root', 'root'), - 'mobilegps' => array('/etc/mobilegps', 644, 'root', 'root'), - 'starnetserver' => array('/etc/starnetserver', 644, 'root', 'root'), - 'timeserver' => array('/etc/timeserver', 644, 'root', 'root'), - // Mode markers (operator has at most one of these) - 'dstar-radio.mmdvmhost' => array('/etc/dstar-radio.mmdvmhost', 644, 'root', 'root'), - 'dstar-radio.dstarrepeater' => array('/etc/dstar-radio.dstarrepeater', 644, 'root', 'root'), - // Pi-Star service / dashboard config - 'pistar-remote' => array('/etc/pistar-remote', 644, 'root', 'root'), - 'hosts' => array('/etc/hosts', 644, 'root', 'root'), - 'hostname' => array('/etc/hostname', 644, 'root', 'root'), - // .key files: 600 www-data so unprivileged dashboard reads - // (banner_warnings.inc, bm_links.php, bm_manager.php — all - // parse_ini_file() without sudo) still work post-restore. - 'bmapi.key' => array('/etc/bmapi.key', 600, 'www-data', 'www-data'), - 'dapnetapi.key' => array('/etc/dapnetapi.key', 600, 'www-data', 'www-data'), - 'pistar-css.ini' => array('/etc/pistar-css.ini', 644, 'root', 'root'), - 'RSSI.dat' => array('/usr/local/etc/RSSI.dat', 644, 'root', 'root'), - 'ircddblocal.php' => array('/var/www/dashboard/config/ircddblocal.php', 644, 'root', 'root'), - 'config.php' => array('/var/www/dashboard/config/config.php', 644, 'root', 'root'), - ); -} - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before the download / restore handlers run. -// -// CSRF protection here makes C1's zip-slip / restore-pipeline RCE -// harder to exploit (attacker can no longer trigger restore via a -// cross-site click); the underlying bugs in the restore handler -// remain — they are tracked separately as the C1/C2 work-on-hold. -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('config/language.php'); // Load the Pi-Star Release file @@ -150,10 +11,7 @@ require_once('config/version.php'); if ($_SERVER["PHP_SELF"] == "/admin/config_backup.php") { // Sanity Check Passed. header('Cache-Control: no-cache'); - // session_start() is no longer called here — csrf_verify() at - // the top of the file already started the session via - // csrf_session_start(). A second session_start() would emit a - // "session is already active" NOTICE on PHP 8.x. + session_start(); ?> @@ -164,79 +22,75 @@ if ($_SERVER["PHP_SELF"] == "/admin/config_backup.php") { - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['backup_restore'];?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['backup_restore'];?> -
-
Pi-Star: /
-

Pi-Star

+
CDN: /
+

CDN

| | | - |

+

'."\n"; + echo '
'."\n"; - if ( $_POST["action"] === "download" ) { - echo "".$lang['backup_restore']."\n"; + if ( escapeshellcmd($_POST["action"]) == "download" ) { $output = "Finding config files to be backed up\n"; $backupDir = "/tmp/config_backup"; $backupZip = "/tmp/config_backup.zip"; - $hostNameInfo = exec('cat /etc/hostname'); - - $output .= shell_exec("sudo rm -rf " . escapeshellarg($backupZip) . " 2>&1"); - $output .= shell_exec("sudo rm -rf " . escapeshellarg($backupDir) . " 2>&1"); - $output .= shell_exec("sudo mkdir " . escapeshellarg($backupDir) . " 2>&1"); - - // Iterate the canonical backup map so the backup and the - // restore allowlist cannot drift from each other. dhcpcd.conf - // is special-cased (only included when the operator has a - // static IP configured) — everything else is unconditional; - // missing source files are silently skipped (the cp returns - // an error to stderr that nobody reads, same as the legacy - // behaviour). - foreach (backup_files() as $basename => $meta) { - // $meta is [path, mode, owner, group]. The backup half - // only needs the path — mode/owner/group are consumed - // on the restore-half install command. - $srcpath = $meta[0]; - if ($basename === 'dhcpcd.conf') { - // Only back up dhcpcd.conf if the operator has set a - // static IP — otherwise restoring would clobber - // working DHCP config on the target device. - if (!shell_exec('cat /etc/dhcpcd.conf | grep "static ip_address" | grep -v "#"')) { - continue; - } - } - if (file_exists($srcpath)) { - $output .= shell_exec( - "sudo cp " . escapeshellarg($srcpath) . " " - . escapeshellarg($backupDir . '/' . $basename) . " 2>&1" - ); - } - } - + $hostNameInfo = exec('cat /etc/hostname'); + + $output .= shell_exec("sudo rm -rf $backupZip 2>&1"); + $output .= shell_exec("sudo rm -rf $backupDir 2>&1"); + $output .= shell_exec("sudo mkdir $backupDir 2>&1"); + if (shell_exec('cat /etc/dhcpcd.conf | grep "static ip_address" | grep -v "#"')) { + $output .= shell_exec("sudo cp /etc/dhcpcd.conf $backupDir 2>&1"); + } + $output .= shell_exec("sudo cp /etc/wpa_supplicant/wpa_supplicant.conf $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/ircddbgateway $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/mmdvmhost $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/dstarrepeater $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/dapnetgateway $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/p25gateway $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/m17gateway $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/ysfgateway $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/ysf2dmr $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/dgidgateway $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/nxdngateway $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/dmrgateway $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/mobilegps $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/starnetserver $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/timeserver $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/dstar-radio.* $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/pistar-remote $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/hosts $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/hostname $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/bmapi.key $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/dapnetapi.key $backupDir 2>&1"); + $output .= shell_exec("sudo cp /etc/pistar-css.ini $backupDir 2>&1"); + $output .= shell_exec("sudo cp /usr/local/etc/RSSI.dat $backupDir 2>&1"); + $output .= shell_exec("sudo cp /var/www/dashboard/config/ircddblocal.php $backupDir 2>&1"); + $output .= shell_exec("sudo cp /var/www/dashboard/config/config.php $backupDir 2>&1"); $output .= "Compressing backup files\n"; - $output .= shell_exec("sudo zip -j " . escapeshellarg($backupZip) . " " . escapeshellarg($backupDir) . "/* 2>&1"); + $output .= shell_exec("sudo zip -j $backupZip $backupDir/* 2>&1"); $output .= "Starting download\n"; - - echo "
"
-             . htmlspecialchars($output, ENT_QUOTES, 'UTF-8') . "
\n"; + + echo "
$output
\n"; if (file_exists($backupZip)) { $utc_time = gmdate('Y-m-d H:i:s'); @@ -247,12 +101,12 @@ if ($_SERVER["PHP_SELF"] == "/admin/config_backup.php") { $local_time = $dt->format('Y-M-d'); header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); - if ($hostNameInfo != "pi-star") { - header('Content-Disposition: attachment; filename="'.basename("Pi-Star_Config_".$hostNameInfo."_".$local_time.".zip").'"'); - } - else { - header('Content-Disposition: attachment; filename="'.basename("Pi-Star_Config_$local_time.zip").'"'); - } + if ($hostNameInfo != "cdn") { + header('Content-Disposition: attachment; filename="'.basename("CDN_Config_".$hostNameInfo."_".$local_time.".zip").'"'); + } + else { + header('Content-Disposition: attachment; filename="'.basename("CDN_Config_$local_time.zip").'"'); + } header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate'); @@ -265,353 +119,149 @@ if ($_SERVER["PHP_SELF"] == "/admin/config_backup.php") { } }; - if ( $_POST["action"] === "restore" ) { - echo "Config Restore\n"; + if ( escapeshellcmd($_POST["action"]) == "restore" ) { $output = "Uploading your Config data\n"; - // Wrap the whole restore in a do/while(false) so an early - // bail-out (upload validation failure, ZIP parse error, - // unsafe entry name, etc.) can break cleanly out of the - // sequence without an `if/else` pyramid. PHP 7.0+ idiom. - do { + $target_dir = "/tmp/config_restore/"; + shell_exec("sudo rm -rf $target_dir 2>&1"); + shell_exec("mkdir $target_dir 2>&1"); + if($_FILES["fileToUpload"]["name"]) { + $filename = $_FILES["fileToUpload"]["name"]; + $source = $_FILES["fileToUpload"]["tmp_name"]; + $type = $_FILES["fileToUpload"]["type"]; + + $name = explode(".", $filename); + $accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed'); + foreach($accepted_types as $mime_type) { + if($mime_type == $type) { + $okay = true; + break; + } + } + } + $continue = strtolower($name[1]) == 'zip' ? true : false; + if(!$continue) { + $output .= "The file you are trying to upload is not a .zip file. Please try again.\n"; + } + $target_path = $target_dir.$filename; + + if(move_uploaded_file($source, $target_path)) { + $zip = new ZipArchive(); + $x = $zip->open($target_path); + if ($x === true) { + $zip->extractTo($target_dir); // change this to the correct site path + $zip->close(); + unlink($target_path); + } + $output .= "Your .zip file was uploaded and unpacked.\n"; + $output .= "Stopping Services.\n"; + + // Stop the DV Services + shell_exec('sudo systemctl stop cron.service 2>&1'); //Cron + shell_exec('sudo systemctl stop dstarrepeater.service 2>&1'); //D-Star Radio Service + shell_exec('sudo systemctl stop mmdvmhost.service 2>&1'); //MMDVMHost Radio Service + shell_exec('sudo systemctl stop ircddbgateway.service 2>&1'); //ircDDBGateway Service + shell_exec('sudo systemctl stop timeserver.service 2>&1'); //Time Server Service + shell_exec('sudo systemctl stop pistar-watchdog.service 2>&1'); //PiStar-Watchdog Service + shell_exec('sudo systemctl stop pistar-remote.service 2>&1'); //PiStar-Remote Service + shell_exec('sudo systemctl stop ysfgateway.service 2>&1'); //YSFGateway + shell_exec('sudo systemctl stop ysf2dmr.service 2>&1'); //YSF2DMR + shell_exec('sudo systemctl stop p25gateway.service 2>&1'); //P25Gateway + shell_exec('sudo systemctl stop nxdngateway.service 2>&1'); //NXDNGateway + shell_exec('sudo systemctl stop m17gateway.service 2>&1'); //M17Gateway + shell_exec('sudo systemctl stop dapnetgateway.service 2>&1'); //DAPNETGateway + shell_exec('sudo systemctl stop mobilegps.service 2>&1'); //MobileGPS + + // Make the disk Writable + shell_exec('sudo mount -o remount,rw / 2>&1'); + + // Overwrite the configs + $output .= "Writing new Config\n"; + $output .= shell_exec("sudo rm -f /etc/dstar-radio.* 2>&1")."\n"; + $output .= shell_exec("sudo mv -f /tmp/config_restore/RSSI.dat /usr/local/etc/ 2>&1")."\n"; + $output .= shell_exec("sudo mv -f /tmp/config_restore/ircddblocal.php /var/www/dashboard/config/ 2>&1")."\n"; + $output .= shell_exec("sudo mv -f /tmp/config_restore/config.php /var/www/dashboard/config/ 2>&1")."\n"; + $output .= shell_exec("sudo mv -v -f /tmp/config_restore/wpa_supplicant.conf /etc/wpa_supplicant/ 2>&1")."\n"; + $output .= shell_exec("sudo mv -v -f /tmp/config_restore/* /etc/ 2>&1")."\n"; + + //Restore the Timezone Config + $timeZone = shell_exec('grep date /var/www/dashboard/config/config.php | grep -o "\'.*\'" | sed "s/\'//g"'); + $timeZone = preg_replace( "/\r|\n/", "", $timeZone); //Remove the linebreaks + shell_exec('sudo timedatectl set-timezone '.$timeZone.' 2>&1'); + + //Restore ircDDGBateway Link Manager Password + $ircRemotePassword = shell_exec('grep remotePassword /etc/ircddbgateway | awk -F\'=\' \'{print $2}\''); + shell_exec('sudo sed -i "/password=/c\\password='.$ircRemotePassword.'" /root/.Remote\ Control'); - // Hardened restore pipeline. See the file-level docblock for - // the security model. Constants here: - // - $target_dir is hardcoded; the operator-supplied filename - // never touches a path concat. - // - $upload_path is also hardcoded; we move the uploaded - // temp file to a known name before any further processing. - // - $max_zip_bytes caps the upload; a real Pi-Star backup - // is ~25 KB, nginx already caps the body at 512 KB, so - // 256 KB is generous. - $target_dir = '/tmp/config_restore'; - $upload_path = '/tmp/config_restore_upload.zip'; - $max_zip_bytes = 256 * 1024; - $allowlist = backup_files(); + // Make the disk Read-Only + shell_exec('sudo mount -o remount,ro / 2>&1'); + + // Start the services + $output .= "Starting Services.\n"; + shell_exec('sudo systemctl start dstarrepeater.service 2>&1'); //D-Star Radio Service + shell_exec('sudo systemctl start mmdvmhost.service 2>&1'); //MMDVMHost Radio Service + shell_exec('sudo systemctl start ircddbgateway.service 2>&1'); //ircDDBGateway Service + shell_exec('sudo systemctl start timeserver.service 2>&1'); //Time Server Service + shell_exec('sudo systemctl start pistar-watchdog.service 2>&1'); //PiStar-Watchdog Service + shell_exec('sudo systemctl start pistar-remote.service 2>&1'); //PiStar-Remote Service + if (substr(exec('grep "pistar-upnp.service" /etc/crontab | cut -c 1'), 0, 1) !== '#') { + shell_exec('sudo systemctl start pistar-upnp.service 2>&1'); //PiStar-UPnP Service + } + shell_exec('sudo systemctl start ysfgateway.service 2>&1'); //YSFGateway + shell_exec('sudo systemctl start ysf2dmr.service 2>&1'); //YSF2DMR + shell_exec('sudo systemctl start p25gateway.service 2>&1'); //P25Gateway + shell_exec('sudo systemctl start nxdngateway.service 2>&1'); //NXDNGateway + shell_exec('sudo systemctl start m17gateway.service 2>&1'); //M17Gateway + shell_exec('sudo systemctl start dapnetgateway.service 2>&1'); //DAPNETGateway + shell_exec('sudo systemctl start mobilegps.service 2>&1'); //MobileGPS + shell_exec('sudo systemctl start cron.service 2>&1'); //Cron + + // Complete + $output .= "Configuration Restore Complete.\n"; + } + else { + $output .= "There was a problem with the upload. Please try again.
"; + $output .= "\n".'
'."\n"; + $output .= ''."\n"; + } + echo "
$output
\n"; + }; - shell_exec("sudo rm -rf " . escapeshellarg($target_dir) . " 2>&1"); - shell_exec("rm -f " . escapeshellarg($upload_path) . " 2>&1"); - shell_exec("mkdir -p " . escapeshellarg($target_dir) . " 2>&1"); - - // ----- Upload validation ------------------------------------- - $upload_ok = false; - $err_msg = ''; - if (!isset($_FILES['fileToUpload']) || - $_FILES['fileToUpload']['error'] !== UPLOAD_ERR_OK) { - $err_msg = 'No file uploaded, or upload failed.'; - } elseif ($_FILES['fileToUpload']['size'] <= 0 || - $_FILES['fileToUpload']['size'] > $max_zip_bytes) { - $err_msg = 'Upload size out of range (expected up to ' - . round($max_zip_bytes / 1024) . ' KB).'; - } else { - $tmp_name = $_FILES['fileToUpload']['tmp_name']; - // finfo_file() reads the magic bytes — much harder for an - // attacker to fake than the client-supplied $_FILES['type']. - $finfo = finfo_open(FILEINFO_MIME_TYPE); - $magic = $finfo ? finfo_file($finfo, $tmp_name) : ''; - if ($finfo) finfo_close($finfo); - if ($magic !== 'application/zip') { - $err_msg = 'Uploaded file is not a ZIP archive (detected ' - . htmlspecialchars($magic, ENT_QUOTES, 'UTF-8') . ').'; - } elseif (!move_uploaded_file($tmp_name, $upload_path)) { - $err_msg = 'Could not stage upload to ' . $upload_path . '.'; - } else { - $upload_ok = true; - } - } - - if (!$upload_ok) { - $output .= $err_msg . "\n"; - echo "
"
-                 . htmlspecialchars($output, ENT_QUOTES, 'UTF-8') . "
\n"; - // Don't emit here — the outer code does it once - // after the if-action blocks finish. The "Go Back" button - // is rendered AFTER the table closes (see end of file). - break; - } - - // ----- ZIP entry validation --------------------------------- - // Open the archive and decide which entries to extract BEFORE - // any extraction happens. An entry is admitted iff: - // - its name appears verbatim as a key in $allowlist - // (basename → target map), AND - // - its name contains no `/`, no `\`, and does not start - // with `.` (defence in depth — the backup writer uses - // `zip -j` so directory components are never legitimate). - // Entries outside the allowlist are silently skipped — that's - // the documented behaviour for forward-compat with future - // Pi-Star versions adding new files. - $zip = new ZipArchive(); - if ($zip->open($upload_path) !== true) { - $output .= "Could not open the uploaded ZIP.\n"; - @unlink($upload_path); - echo "
"
-                 . htmlspecialchars($output, ENT_QUOTES, 'UTF-8') . "
\n"; - break; - } - - $admit = array(); - for ($i = 0; $i < $zip->numFiles; $i++) { - $name = $zip->getNameIndex($i); - if ($name === false || $name === '') { - continue; - } - if (strpos($name, '/') !== false || - strpos($name, '\\') !== false || - strpos($name, "\0") !== false || - $name[0] === '.') { - // Path-traversal / hidden / NUL-injection attempt. - // Reject the whole archive — this is well outside any - // Pi-Star-generated backup shape. break 2 exits the - // for() AND the surrounding do/while(false) early- - // exit block in one hop. - $zip->close(); - @unlink($upload_path); - $output .= "Refusing ZIP — entry '" - . htmlspecialchars(substr($name, 0, 64), ENT_QUOTES, 'UTF-8') - . "' has an unsafe name.\n"; - error_log("config_backup: rejected ZIP with unsafe entry '$name'"); - echo "
"
-                     . htmlspecialchars($output, ENT_QUOTES, 'UTF-8') . "
\n"; - break 2; - } - if (isset($allowlist[$name])) { - $admit[$name] = $i; - } - // else: silently ignored — unknown filename. - } - - // Extract only the admitted entries into $target_dir. We use - // ZipArchive::extractTo() with an explicit entry list so - // ANYTHING outside that list is left in the archive and - // never written to disk. - $entries_to_extract = array_keys($admit); - if (empty($entries_to_extract)) { - $zip->close(); - @unlink($upload_path); - $output .= "ZIP contained no recognised Pi-Star config files.\n"; - echo "
"
-                 . htmlspecialchars($output, ENT_QUOTES, 'UTF-8') . "
\n"; - break; - } - if (!$zip->extractTo($target_dir, $entries_to_extract)) { - $zip->close(); - @unlink($upload_path); - $output .= "Failed to extract ZIP entries.\n"; - echo "
"
-                 . htmlspecialchars($output, ENT_QUOTES, 'UTF-8') . "
\n"; - break; - } - $zip->close(); - @unlink($upload_path); - $output .= "Your .zip file was uploaded and unpacked (" - . count($entries_to_extract) . " files).\n"; - - // ----- Service stop ---------------------------------------- - $output .= "Stopping Services.\n"; - $stop_services = array( - 'cron.service', 'dstarrepeater.service', 'mmdvmhost.service', - 'ircddbgateway.service', 'timeserver.service', - 'pistar-watchdog.service', 'pistar-remote.service', - 'ysfgateway.service', 'ysf2dmr.service', 'p25gateway.service', - 'nxdngateway.service', 'm17gateway.service', - 'dapnetgateway.service', 'mobilegps.service', - ); - foreach ($stop_services as $svc) { - shell_exec('sudo systemctl stop ' . escapeshellarg($svc) . ' 2>&1'); - } - - shell_exec('sudo mount -o remount,rw / 2>&1'); - - // ----- Per-file install ------------------------------------ - // Replace the previous blind `sudo mv -v -f /tmp/.../* /etc/` - // with a per-file `sudo install -m 644 -o root -g root` driven - // by the canonical map. install is atomic on same-fs (rename) - // and falls back to safe copy across filesystems. The mode and - // owner are forced regardless of how the file arrived in the - // archive. - $output .= "Writing new Config\n"; - - // Tear down stale dstar-radio.* markers first — only one of - // the two can be in use, and the restored archive may carry - // a different mode than the device currently has. Use - // `rm -rf` (not `rm -f`) so the call matches the - // PISTAR_DASH_MARKERS sudoers entry — different argv tokens - // yield different sudoers matches, and only `-rf` is - // allowlisted. - shell_exec('sudo rm -rf /etc/dstar-radio.* 2>&1'); - - $installed = 0; - foreach ($admit as $basename => $_idx) { - $src = $target_dir . '/' . $basename; - $meta = $allowlist[$basename]; - $target = $meta[0]; - $mode = (string)$meta[1]; - $owner = $meta[2]; - $group = $meta[3]; - if (!file_exists($src)) { - // Should be impossible after a successful extractTo, - // but guard anyway — extraction can fail per-entry on - // unusual archives without throwing. - continue; - } - // Per-file install args from backup_files() metadata — - // mode/owner/group must match the deployed sudoers - // PISTAR_DASH_INSTALL line for $target or sudo will - // reject. The hardcoded `install -m 644 -o root -g root` - // here used to silently fail on .key files (require - // 600 www-data:www-data) and wpa_supplicant.conf - // (600 root:root) under the path-scoped sudoers. - $cmd = 'sudo install -m ' . $mode - . ' -o ' . escapeshellarg($owner) - . ' -g ' . escapeshellarg($group) . ' ' - . escapeshellarg($src) . ' ' - . escapeshellarg($target); - $rc = 0; $cmd_out = array(); - exec($cmd . ' 2>&1', $cmd_out, $rc); - if ($rc === 0) { - $installed++; - } else { - $output .= " install failed for $basename: " - . implode(' / ', $cmd_out) . "\n"; - } - } - $output .= "Installed $installed file(s).\n"; - - // ----- Post-restore re-applies (data-side, not shell) ----- - - // Timezone: the restored config.php contains the operator's - // timezone in a date_default_timezone_set('…') call. We want - // the OS clock to match the dashboard's view. PRE-fix this - // path was a shell pipeline interpolating the grepped value; - // post-fix we extract via PHP-side parsing and validate - // strictly against PHP's own list of valid timezone IDs - // before passing through escapeshellarg(). - $cfg_path = '/var/www/dashboard/config/config.php'; - if (is_readable($cfg_path)) { - $cfg = file_get_contents($cfg_path); - if (preg_match("/date_default_timezone_set\\(\\s*['\"]([^'\"]+)['\"]\\s*\\)/", - $cfg, $m)) { - $tz = $m[1]; - if (in_array($tz, DateTimeZone::listIdentifiers(), true)) { - shell_exec('sudo timedatectl set-timezone ' - . escapeshellarg($tz) . ' 2>&1'); - } else { - error_log("config_backup: skipping unknown timezone '$tz' from restored config.php"); - } - } - } - - // ircDDBGateway Remote Control password: the restored - // /etc/ircddbgateway carries `remotePassword=...`; the - // /root/.Remote Control sibling file (mode 600 root:root, - // not in the backup set) needs the same value or the - // remotecontrold tool can't reach the daemon. - // - // Pre-fix this was a shell-interpolated `sudo sed -i ...`. - // Post-fix: read via PHP-side fopen/fgets (the file is mode - // 644 root:root after we just installed it, so www-data can - // read it back), validate, then route through the helper's - // privileged-flat editor — same primitive the C6.7 fix uses - // and also what the configure.php confPassword handler now - // uses. No shell ever sees the value. - $rp_target = '/etc/ircddbgateway'; - if (is_readable($rp_target)) { - $rp = ''; - foreach (file($rp_target, FILE_IGNORE_NEW_LINES) as $line) { - if (strpos($line, 'remotePassword=') === 0) { - $rp = substr($line, strlen('remotePassword=')); - break; - } - } - // ircDDBGateway accepts arbitrary printable bytes for the - // password; the helper's NUL/CR/LF guard is the floor. - if ($rp !== '' && !preg_match('/[\x00\r\n]/', $rp)) { - config_writer_stage_privileged_flat( - '/root/.Remote Control', 'password', $rp - ); - config_writer_commit(false); - } - } - - shell_exec('sudo mount -o remount,ro / 2>&1'); - - // ----- Service start --------------------------------------- - $output .= "Starting Services.\n"; - $start_services = array( - 'dstarrepeater.service', 'mmdvmhost.service', - 'ircddbgateway.service', 'timeserver.service', - 'pistar-watchdog.service', 'pistar-remote.service', - ); - foreach ($start_services as $svc) { - shell_exec('sudo systemctl start ' . escapeshellarg($svc) . ' 2>&1'); - } - if (substr(exec('grep "pistar-upnp.service" /etc/crontab | cut -c 1'), 0, 1) !== '#') { - shell_exec('sudo systemctl start pistar-upnp.service 2>&1'); - } - $start_services_after_upnp = array( - 'ysfgateway.service', 'ysf2dmr.service', 'p25gateway.service', - 'nxdngateway.service', 'm17gateway.service', - 'dapnetgateway.service', 'mobilegps.service', 'cron.service', - ); - foreach ($start_services_after_upnp as $svc) { - shell_exec('sudo systemctl start ' . escapeshellarg($svc) . ' 2>&1'); - } - - // Cleanup: remove the staged extraction dir so subsequent - // restores don't see leftovers. - shell_exec("sudo rm -rf " . escapeshellarg($target_dir) . " 2>&1"); - - $output .= "Configuration Restore Complete.\n"; - echo "
"
-             . htmlspecialchars($output, ENT_QUOTES, 'UTF-8') . "
\n"; - - } while (false); // end do/while(false) early-exit block - }; - - echo "\n"; + echo "
\n"; } else { ?>
" method="post" enctype="multipart/form-data"> - - - - - - - - - - - - -
Download Configuration
- -
Restore Configuration
-
- -
-
- WARNING:
- Editing the files outside of Pi-Star *could* have un-desireable side effects.
-
- This backup and restore tool, will backup your config files to a Zip file, and allow you to restore them later
- either to this Pi-Star or another one.
-
    -
  • System Passwords / Dashboard passwords are NOT backed up / restored.
  • -
  • Wireless Configuration IS backed up and restored
  • -
-
+
+ +
+ Restore Config + Restore Configuration + + +
+
+
+
+ WARNING: Editing the files outside of CDN *could* have un-desireable side effects.
+ This backup and restore tool will back up your config files to a Zip file, and allow you to restore them later, either to this CDN or another one. +
    +
  • System Passwords / Dashboard passwords are NOT backed up / restored.
  • +
  • Wireless Configuration IS backed up and restored
  • +
+
+
-
-
diff --git a/admin/css b/admin/css deleted file mode 100644 index d2d7c52..0000000 --- a/admin/css +++ /dev/null @@ -1 +0,0 @@ -../css \ No newline at end of file diff --git a/admin/css/index.php b/admin/css/index.php new file mode 100644 index 0000000..e69de29 diff --git a/admin/css/ircddb.css b/admin/css/ircddb.css new file mode 100644 index 0000000..c6b5523 --- /dev/null +++ b/admin/css/ircddb.css @@ -0,0 +1,328 @@ +.container { + width: 820px; + text-align: left; + margin: auto; +} + +body, font { + font: 12px verdana,arial,sans-serif; + color: #ffffff; +} + +.header { + background : #dd4b39; + text-decoration : none; + color : #ffffff; + font-family : verdana, arial, sans-serif; + text-align : left; + padding : 5px 0px 5px 0px; + border-radius : 10px 10px 0 0; + } + +.nav { + float : left; + margin : 0; + padding : 3px 3px 3px 3px; + width : 160px; + background : #242d31; + font-weight : normal; + min-height : 100%; +} + +.content { + margin : 0 0 0 166px; + padding : 1px 5px 5px 5px; + color : #000000; + background : #ffffff; + text-align: center; +} + +.contentwide { + padding: 5px 5px 5px 5px; + color: #000000; + background: #ffffff; + text-align: center; +} + +.footer { + background : #dd4b39; + text-decoration : none; + color : #ffffff; + font-family : verdana, arial, sans-serif; + font-size : 9px; + text-align : center; + padding : 10px 0 10px 0; + border-radius : 0 0 10px 10px; + clear : both; +} + +#tail { + height: 450px; + width: 805px; + overflow-y: scroll; + overflow-x: scroll; + color: #00ff00; + background: #000000; +} + +table { + vertical-align: middle; + text-align: center; + empty-cells: show; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; + border-collapse:collapse; + border-color: #000000; + border-style: solid; + border-spacing: 4px; + border-width: 2px; + text-decoration: none; + color: #ffffff; + background: #000000; + font-family: verdana,arial,sans-serif; + width: 100%; + white-space: nowrap; +} + +table th { + font-family: "Lucidia Console",Monaco,monospace; + text-shadow: 1px 1px #8b0000; + text-decoration: none; + background: #dd4b39; + border: 1px solid #c0c0c0; +} + +table tr:nth-child(even) { + background: #f7f7f7; +} + +table tr:nth-child(odd) { + background: #d0d0d0; +} + +table td { + color: #000000; + font-family: "Lucidia Console",Monaco,monospace; + text-decoration: none; + border: 1px solid #000000; + overflow-x: hidden; +} + +body { + background: #edf0f5; + color: #000000; +} + +a { + text-decoration:none; + +} + +a:link, a:visited { + text-decoration: none; + color: #0000e0; + font-weight: normal; +} + +a.tooltip, a.tooltip:link, a.tooltip:visited, a.tooltip:active { + text-decoration: none; + position: relative; + color: #FFFFFF; +} + +a.tooltip:hover { + text-shadow: none; + text-decoration: none; + color: #FFFFFF; + background: transparent; +} + +a.tooltip span { + text-shadow: none; + text-decoration: none; + display: none; +} + +a.tooltip:hover span { + text-shadow: none; + text-decoration: none; + display: block; + position: absolute; + top: 20px; + left: 0; + width: 200px; + z-index: 100; + color: #000000; + border:1px solid #000000; + background: #f7f7f7; + font: 12px Verdana, sans-serif; + text-align: left; +} + +a.tooltip span b { + text-shadow: none; + text-decoration: none; + display: block; + color: #000000; + margin: 0; + padding: 0; + font-size: 12px; + font-weight: bold; + border: 0px; + border-bottom: 1px solid black; + background: #d0d0d0; +} + +a.tooltip2, a.tooltip2:link, a.tooltip2:visited, a.tooltip2:active { + text-shadow: none; + text-decoration: none; + position: relative; + font-weight: bold; + color: #000000; +} + +a.tooltip2:hover { + text-shadow: none; + text-decoration: none; + color: #000000; + background: transparent; +} + +a.tooltip2 span { + text-shadow: none; + text-decoration: none; + display: none; +} + +a.tooltip2:hover span { + text-shadow: none; + text-decoration: none; + display: block; + position: absolute; + top: 20px; + left: 0; + width: 200px; + z-index: 100; + color: #000000; + border:1px solid #000000; + background: #f7f7f7; + font: 12px Verdana, sans-serif; + text-align: left; +} + +a.tooltip2 span b { + text-shadow: none; + text-decoration: none; + display: block; + color: #000000; + margin: 0; + padding: 0; + font-size: 12px; + font-weight: bold; + border: 0px; + border-bottom: 1px solid black; + background: #d0d0d0; +} + +ul { + padding: 5px; + margin: 10px 0; + list-style: none; + float: left; +} + +ul li { + float: left; + display: inline; /*For ignore double margin in IE6*/ + margin: 0 10px; +} + +ul li a { + text-decoration: none; + float:left; + color: #999; + cursor: pointer; + font: 900 14px/22px "Arial", Helvetica, sans-serif; +} + +ul li a span { + margin: 0 10px 0 -10px; + padding: 1px 8px 5px 18px; + position: relative; /*To fix IE6 problem (not displaying)*/ + float:left; +} + +ul.mmenu li a.current, ul.mmenu li a:hover { + background: url(/images/buttonbg.png) no-repeat top right; + color: #0d5f83; +} + +ul.mmenu li a.current span, ul.mmenu li a:hover span { + background: url(/images/buttonbg.png) no-repeat top left; +} + +h1 { + text-shadow: 2px 2px #303030; + text-align: center; +} + +/* CSS Toggle Code here */ +.toggle { + position: absolute; + margin-left: -9999px; + visibility: hidden; +} + +.toggle + label { + display: block; + position: relative; + cursor: pointer; + outline: none; +} + +input.toggle-round-flat + label { + padding: 1px; + width: 33px; + height: 18px; + background-color: #dddddd; + border-radius: 10px; + transition: background 0.4s; +} + +input.toggle-round-flat + label:before, +input.toggle-round-flat + label:after { + display: block; + position: absolute; + content: ""; +} + +input.toggle-round-flat + label:before { + top: 1px; + left: 1px; + bottom: 1px; + right: 1px; + background-color: #fff; + border-radius: 10px; + transition: background 0.4s; +} + +input.toggle-round-flat + label:after { + top: 2px; + left: 2px; + bottom: 2px; + width: 16px; + background-color: #dddddd; + border-radius: 12px; + transition: margin 0.4s, background 0.4s; +} + +input.toggle-round-flat:checked + label { + background-color: #dd4b39; +} + +input.toggle-round-flat:checked + label:after { + margin-left: 14px; + background-color: #dd4b39; +} diff --git a/admin/css/mini_ircddb.css b/admin/css/mini_ircddb.css new file mode 100644 index 0000000..51b4f03 --- /dev/null +++ b/admin/css/mini_ircddb.css @@ -0,0 +1,330 @@ +.container { + width: 100%; + text-align: left; + margin: auto; +} + +body, font { + font: 12px verdana,arial,sans-serif; + color: #ffffff; +} + +.header { + background : #dd4b39; + text-decoration : none; + color : #ffffff; + font-family : verdana, arial, sans-serif; + text-align : left; + padding : 5px 0px 5px 0px; + border-radius : 10px 10px 0 0; +} + +.nav { + display: none; + float : left; + margin : 0; + padding : 3px 3px 3px 3px; + width : 160px; + background : #242d31; + font-weight : normal; + min-height : 100%; +} + +.content { + padding: 5px 5px 5px 5px; + color: #000000; + background: #ffffff; + text-align: center; + font-size: 1.4em; +} + +.contentwide { + padding: 5px 5px 5px 5px; + color: #000000; + background: #ffffff; + text-align: center; + font-size: 1.4em; +} + +.footer { + background : #dd4b39; + text-decoration : none; + color : #ffffff; + font-family : verdana, arial, sans-serif; + font-size : 9px; + text-align : center; + padding : 10px 0 10px 0; + border-radius : 0 0 10px 10px; + clear : both; +} + +#tail { + height: 450px; + width: 805px; + overflow-y: scroll; + overflow-x: scroll; + color: #00ff00; + background: #000000; +} + +table { + vertical-align: middle; + text-align: center; + empty-cells: show; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; + border-collapse:collapse; + border-color: #000000; + border-style: solid; + border-spacing: 4px; + border-width: 2px; + text-decoration: none; + color: #ffffff; + background: #000000; + font-family: verdana,arial,sans-serif; + width: 100%; + white-space: nowrap; +} + +table th { + font-family: "Lucidia Console",Monaco,monospace; + text-shadow: 1px 1px #8b0000; + text-decoration: none; + background: #dd4b39; + border: 1px solid #c0c0c0; +} + +table tr:nth-child(even) { + background: #f7f7f7; +} + +table tr:nth-child(odd) { + background: #d0d0d0; +} + +table td { + color: #000000; + font-family: "Lucidia Console",Monaco,monospace; + text-decoration: none; + border: 1px solid #000000; + overflow-x: hidden; +} + +body { + background: #edf0f5; + color: #000000; +} + +a { + text-decoration:none; + +} + +a:link, a:visited { + text-decoration: none; + color: #0000e0; + font-weight: normal; +} + +a.tooltip, a.tooltip:link, a.tooltip:visited, a.tooltip:active { + text-decoration: none; + position: relative; + color: #FFFFFF; +} + +a.tooltip:hover { + text-shadow: none; + text-decoration: none; + color: #FFFFFF; + background: transparent; +} + +a.tooltip span { + text-shadow: none; + text-decoration: none; + display: none; +} + +a.tooltip:hover span { + text-shadow: none; + text-decoration: none; + display: block; + position: absolute; + top: 20px; + left: 0; + width: 200px; + z-index: 100; + color: #000000; + border:1px solid #000000; + background: #f7f7f7; + font: 12px Verdana, sans-serif; + text-align: left; +} + +a.tooltip span b { + text-shadow: none; + text-decoration: none; + display: block; + color: #000000; + margin: 0; + padding: 0; + font-size: 12px; + font-weight: bold; + border: 0px; + border-bottom: 1px solid black; + background: #d0d0d0; +} + +a.tooltip2, a.tooltip2:link, a.tooltip2:visited, a.tooltip2:active { + text-shadow: none; + text-decoration: none; + position: relative; + font-weight: bold; + color: #000000; +} + +a.tooltip2:hover { + text-shadow: none; + text-decoration: none; + color: #000000; + background: transparent; +} + +a.tooltip2 span { + text-shadow: none; + text-decoration: none; + display: none; +} + +a.tooltip2:hover span { + text-shadow: none; + text-decoration: none; + display: block; + position: absolute; + top: 20px; + left: 0; + width: 200px; + z-index: 100; + color: #000000; + border:1px solid #000000; + background: #f7f7f7; + font: 12px Verdana, sans-serif; + text-align: left; +} + +a.tooltip2 span b { + text-shadow: none; + text-decoration: none; + display: block; + color: #000000; + margin: 0; + padding: 0; + font-size: 12px; + font-weight: bold; + border: 0px; + border-bottom: 1px solid black; + background: #d0d0d0; +} + +ul { + padding: 5px; + margin: 10px 0; + list-style: none; + float: left; +} + +ul li { + float: left; + display: inline; /*For ignore double margin in IE6*/ + margin: 0 10px; +} + +ul li a { + text-decoration: none; + float:left; + color: #999; + cursor: pointer; + font: 900 14px/22px "Arial", Helvetica, sans-serif; +} + +ul li a span { + margin: 0 10px 0 -10px; + padding: 1px 8px 5px 18px; + position: relative; /*To fix IE6 problem (not displaying)*/ + float:left; +} + +ul.mmenu li a.current, ul.mmenu li a:hover { + background: url(/images/buttonbg.png) no-repeat top right; + color: #0d5f83; +} + +ul.mmenu li a.current span, ul.mmenu li a:hover span { + background: url(/images/buttonbg.png) no-repeat top left; +} + +h1 { + text-shadow: 2px 2px #303030; + text-align: center; +} + +/* CSS Toggle Code here */ +.toggle { + position: absolute; + margin-left: -9999px; + visibility: hidden; +} + +.toggle + label { + display: block; + position: relative; + cursor: pointer; + outline: none; +} + +input.toggle-round-flat + label { + padding: 1px; + width: 33px; + height: 18px; + background-color: #dddddd; + border-radius: 10px; + transition: background 0.4s; +} + +input.toggle-round-flat + label:before, +input.toggle-round-flat + label:after { + display: block; + position: absolute; + content: ""; +} + +input.toggle-round-flat + label:before { + top: 1px; + left: 1px; + bottom: 1px; + right: 1px; + background-color: #fff; + border-radius: 10px; + transition: background 0.4s; +} + +input.toggle-round-flat + label:after { + top: 2px; + left: 2px; + bottom: 2px; + width: 16px; + background-color: #dddddd; + border-radius: 12px; + transition: margin 0.4s, background 0.4s; +} + +input.toggle-round-flat:checked + label { + background-color: #dd4b39; +} + +input.toggle-round-flat:checked + label:after { + margin-left: 14px; + background-color: #dd4b39; +} diff --git a/admin/css/nice-select.min.css b/admin/css/nice-select.min.css new file mode 100644 index 0000000..206fdd9 --- /dev/null +++ b/admin/css/nice-select.min.css @@ -0,0 +1 @@ +.nice-select{-webkit-tap-highlight-color:rgba(0,0,0,0);background-color:#fff;border-radius:5px;border:solid 1px #e8e8e8;box-sizing:border-box;clear:both;cursor:pointer;display:block;float:left;font-family:inherit;font-size:14px;font-weight:normal;height:38px;line-height:36px;outline:none;padding-left:18px;padding-right:30px;position:relative;text-align:left !important;transition:all .2s ease-in-out;user-select:none;white-space:nowrap;width:auto}.nice-select:hover{border-color:#dbdbdb}.nice-select:active,.nice-select.open,.nice-select:focus{border-color:#999}.nice-select:after{border-bottom:2px solid #999;border-right:2px solid #999;content:"";display:block;height:5px;margin-top:-4px;pointer-events:none;position:absolute;right:12px;top:50%;transform-origin:66% 66%;transform:rotate(45deg);transition:all .15s ease-in-out;width:5px}.nice-select.open:after{transform:rotate(-135deg)}.nice-select.open .nice-select-dropdown{opacity:1;pointer-events:auto;transform:scale(1) translateY(0)}.nice-select.disabled{border-color:#ededed;color:#999;pointer-events:none}.nice-select.disabled:after{border-color:#ccc}.nice-select.wide{width:100%}.nice-select.wide .nice-select-dropdown{left:0 !important;right:0 !important}.nice-select.right{float:right}.nice-select.right .nice-select-dropdown{left:auto;right:0}.nice-select.small{font-size:12px;height:36px;line-height:34px}.nice-select.small:after{height:4px;width:4px}.nice-select.small .option{line-height:34px;min-height:34px}.nice-select .nice-select-dropdown{margin-top:4px;background-color:#fff;border-radius:5px;box-shadow:0 0 0 1px rgba(68,68,68,.11);pointer-events:none;position:absolute;top:100%;left:0;transform-origin:50% 0;transform:scale(0.75) translateY(19px);transition:all .2s cubic-bezier(0.5, 0, 0, 1.25),opacity .15s ease-out;z-index:9;opacity:0}.nice-select .list{border-radius:5px;box-sizing:border-box;overflow:hidden;padding:0;max-height:210px;overflow-y:auto}.nice-select .list:hover .option:not(:hover){background-color:transparent !important}.nice-select .option{cursor:pointer;font-weight:400;line-height:40px;list-style:none;outline:none;padding-left:18px;padding-right:29px;text-align:left;transition:all .2s}.nice-select .option:hover,.nice-select .option.focus,.nice-select .option.selected.focus{background-color:#f6f6f6}.nice-select .option.selected{font-weight:bold}.nice-select .option.disabled{background-color:transparent;color:#999;cursor:default}.nice-select .optgroup{font-weight:bold}.no-csspointerevents .nice-select .nice-select-dropdown{display:none}.no-csspointerevents .nice-select.open .nice-select-dropdown{display:block}.nice-select .list::-webkit-scrollbar{width:0}.nice-select .has-multiple{white-space:inherit;height:auto;padding:7px 12px;min-height:36px;line-height:22px}.nice-select .has-multiple span.current{border:1px solid #ccc;background:#eee;padding:0 10px;border-radius:3px;display:inline-block;line-height:24px;font-size:14px;margin-bottom:3px;margin-right:3px}.nice-select .has-multiple .multiple-options{display:block;line-height:24px;padding:0}.nice-select .nice-select-search-box{box-sizing:border-box;width:100%;padding:5px;pointer-events:none;border-radius:5px 5px 0 0}.nice-select .nice-select-search{box-sizing:border-box;background-color:#fff;border:1px solid #e8e8e8;border-radius:3px;color:#444;display:inline-block;vertical-align:middle;padding:7px 12px;margin:0 10px 0 0;width:100%;min-height:36px;line-height:22px;height:auto;outline:0 !important;font-size:14px} \ No newline at end of file diff --git a/admin/css/pistar-css-mini.php b/admin/css/pistar-css-mini.php new file mode 100644 index 0000000..4eb11ac --- /dev/null +++ b/admin/css/pistar-css-mini.php @@ -0,0 +1,915 @@ + +:root { + --page-bg: #; + --content-bg: #; + --accent: #; + --accent-dark: #; + --accent-light: #; + --accent-text: #; + --banner-drop: #; + --table-head-drop: #; + --content-text: #; + --table-even: #; + --table-odd: #; + --sidebar-bg: #111827; + --sidebar-bg-2: #0b1120; + --sidebar-text: #cbd5e1; + --sidebar-text-dim: #94a3b8; + --sidebar-card-bg: rgba(255,255,255,0.05); + --sidebar-card-strong-bg: rgba(255,255,255,0.09); + --radius: 12px; + --radius-sm: 8px; + --card-border: rgba(15,23,42,0.07); + --shadow-card: 0 1px 2px rgba(15,23,42,0.04), 0 10px 28px -14px rgba(15,23,42,0.16); +} + +html, body { + margin: 0; + padding: 0; +} + +/* Small screens: the rail collapses into a top bar (no fixed sidebar) */ +.container { + width: 100%; + text-align: left; + margin: auto; + background: var(--page-bg); + border-radius: 0; + box-shadow: none; + overflow: visible; +} + +body, font { + font: 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + color: #ffffff; +} + +.header { + position: static; + width: auto; + background: linear-gradient(180deg, var(--sidebar-bg), var(--sidebar-bg-2)); + color: var(--sidebar-text); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + padding: 16px 14px; + box-sizing: border-box; +} + +.header h1 { + font-size: 1.05em; + line-height: 1.3; + color: #ffffff; + text-shadow: none; + text-align: left; + margin: 0 0 4px 0; + padding: 0; + font-weight: 700; +} + +.header > div[style*="font-size: 8px"] { + float: none !important; + text-align: left !important; + color: var(--sidebar-text-dim) !important; + font-size: 10.5px !important; + padding: 0 !important; + margin: 0 0 10px 0; +} + +.header p { + font-size: 0; + margin: 6px 0; + padding: 0; + text-align: left !important; + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 2px; +} + +.header p a, .header p a:link, .header p a:visited { + display: inline-block; + font-size: 13px; + font-weight: 500; + color: var(--sidebar-text) !important; + padding: 8px 10px; + border-radius: 8px; + transition: background 0.15s ease, color 0.15s ease; +} + +.header p a:hover { + background: rgba(255,255,255,0.08); + color: #ffffff !important; +} + +.header p a.active { + background: var(--accent); + color: var(--accent-text) !important; + font-weight: 700; +} + +.header p b { + font-size: 11px; + color: var(--sidebar-text-dim); + display: block; + width: 100%; + margin: 8px 0 2px 2px; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +/* On narrow screens the widgets no longer live in a side column - they + become a full-width panel stacked under the top bar, laid out as a + two-column grid of compact status chips instead of skinny stacked rows. */ +.nav { + display: block; + float: none; + box-sizing: border-box; + margin: 0; + padding: 14px; + width: 100%; + background: linear-gradient(180deg, var(--sidebar-bg), var(--sidebar-bg-2)); + font-weight: normal; + min-height: 0; +} + +.nav table { + width: 100%; + margin: 0 0 12px 0; + border-collapse: separate; + border-spacing: 4px; + table-layout: fixed; + white-space: normal; +} + +.nav table th[colspan] { + background: transparent; + color: var(--sidebar-text-dim); + text-align: left; + text-transform: uppercase; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.06em; + padding: 10px 2px 6px 2px; + border: none; +} + +.nav table:first-child th[colspan] { + padding-top: 0; +} + +.nav table th:not([colspan]) { + background: var(--sidebar-card-bg); + color: var(--sidebar-text-dim); + text-align: left; + font-size: 10.5px; + font-weight: 700; + padding: 7px 8px; + border: none; + border-radius: var(--radius-sm); + width: 30%; +} + +.nav table td { + color: var(--sidebar-text); + background: var(--sidebar-card-bg); + font-size: 11px; + font-weight: 600; + padding: 7px 8px; + border: none; + border-radius: var(--radius-sm); +} + +.nav table td[style*="fff"] { + background: var(--sidebar-card-strong-bg) !important; + color: var(--sidebar-text) !important; +} + +.nav table tr:nth-child(even), +.nav table tr:nth-child(odd) { + background: transparent; +} + +.nav table a { color: #ffffff; font-weight: 700; } + +#lastHerd, #localTxs, #Pages, #sysInfo, +#refLinks, #cssConnects, #lh, #localTx, #bmConnects, #tgifConnects { + margin: 14px; + background: var(--content-bg); + border: 1px solid var(--card-border); + border-radius: var(--radius); + box-shadow: var(--shadow-card); + padding: 14px 14px 18px 14px; + box-sizing: border-box; + overflow-x: auto; +} + +#lastHerd > b, #localTxs > b, #Pages > b, #sysInfo > b, +#refLinks > b, #cssConnects > b, #lh > b, #localTx > b, #bmConnects > b, #tgifConnects > b { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + font-weight: 700; + color: var(--content-text); + margin: 0 0 12px 0; + padding-bottom: 10px; + border-bottom: 1px solid var(--card-border); +} + +#lastHerd > b::before, #localTxs > b::before, #Pages > b::before, #sysInfo > b::before, +#refLinks > b::before, #cssConnects > b::before, #lh > b::before, #localTx > b::before, #bmConnects > b::before, #tgifConnects > b::before { + content: ""; + width: 8px; + height: 8px; + border-radius: 2px; + background: var(--accent); + flex: none; +} + +.content { + padding: 6px 0 5px 0; + color: var(--content-text); + background: var(--page-bg); + text-align: left; + font-size: 1.4em; +} + +.contentwide { + padding: 16px; + color: var(--content-text); + background: var(--page-bg); + text-align: center; + font-size: 1.4em; +} + +.contentwide h2 { + color: var(--content-text); + font: 600 1em -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + padding: 0 0 8px 10px; + margin: 24px 0 10px 0; + border-left: 4px solid var(--accent); + border-bottom: 1px solid rgba(0,0,0,0.08); +} + +.contentwide h2:first-child { + margin-top: 0; +} + +/* Inline "Alert: ..." banners used across the dashboard (config warnings etc.) */ +.alert-banner-table { + margin: 0 0 16px 0 !important; + width: 100% !important; +} + +.alert-banner-table, .alert-banner-table tr { + background: transparent !important; +} + +.alert-cell { + text-align: left !important; + border-radius: 8px; + padding: 12px 16px !important; + font-weight: 500; + border: 1px solid transparent; +} + +.alert-warning { + background: #fffbeb; + color: #92400e; + border-color: #fde68a; +} + +.alert-danger { + background: #fef2f2; + color: #b91c1c; + border-color: #fecaca; +} + +.alert-warning a, .alert-danger a { + color: inherit; + text-decoration: underline; +} + +/* Settings-card system (mirrors pistar-css.php) - this was missing from the + mobile stylesheet entirely, so every config/editor page rendered as + unstyled plain divs below the 830px breakpoint. Rows stack by default + here since there's no room for the desktop's label+control row. */ +.settings-card { + background: var(--content-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0,0,0,0.04); + padding: 4px 16px; + margin: 0 0 20px 0; + text-align: left; +} + +.settings-card > b:first-child { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + font-weight: 700; + color: var(--content-text); + margin: 14px 0 12px 0; + padding-bottom: 10px; + border-bottom: 1px solid var(--card-border); +} + +.settings-card > b:first-child::before { + content: ""; + width: 8px; + height: 8px; + border-radius: 2px; + background: var(--accent); + flex: none; +} + +.field-row { + display: flex; + flex-direction: column; + align-items: flex-start; + row-gap: 6px; + padding: 12px 0; + border-bottom: 1px solid rgba(0,0,0,0.06); +} + +.field-row:last-child { + border-bottom: none; +} + +.field-label, .field-row > div:first-child { + flex: 0 0 auto; + max-width: none; + font-weight: 500; + font-size: 13px; + color: var(--content-text); + text-align: left; +} + +.field-control, .field-row > div:not(:first-child) { + flex: 1 1 auto; + width: 100%; + box-sizing: border-box; + text-align: left; + color: var(--content-text); + font-size: 13px; +} + +.field-control input[type="text"], .field-control input[type="password"], .field-control input[type="number"], +.field-row input[type="text"], .field-row input[type="password"], .field-row input[type="number"] { + width: 100%; + box-sizing: border-box; + padding: 6px 8px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-control select, .field-row select { + max-width: 100%; + padding: 5px 6px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-note { + font-weight: 400; + font-size: 12.5px; + color: #6b7280; +} + +/* Big icon action buttons (power page, reboot/shutdown) */ +.action-tiles { + display: flex; + flex-wrap: wrap; + gap: 12px; + padding: 14px; +} + +.action-tile { + flex: 1 1 45%; + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + padding: 18px 12px; + background: var(--page-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 10px; + cursor: pointer; + font: 500 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + color: var(--content-text); +} + +.action-tile img { + width: 40px; + height: 40px; +} + +.action-tile-upload { + cursor: default; +} + +.action-tile-upload input[type="file"] { + max-width: 100%; + font-size: 11px; +} + +/* Calibration tool control panels */ +.cal-grid { + display: flex; + flex-wrap: wrap; + gap: 14px; + align-items: flex-start; +} + +.cal-panel { + flex: 1 1 100%; + margin: 0; +} + +.cal-panel table { + width: 100%; +} + +.cal-btn-row { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 0; + flex-wrap: wrap; +} + +/* Raw config-file editors (expert "Full Edit" pages) */ +.raw-editor { + width: 100%; + min-height: 360px; + box-sizing: border-box; + background: #10141a; + color: #d1d5db; + border: 1px solid rgba(0,0,0,0.15); + border-radius: 8px; + padding: 10px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + font-size: 12px; + line-height: 1.5; +} + +.power-status { + background: #10141a; + color: #3ce87a; + border-radius: 8px; + padding: 16px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + line-height: 1.6; +} + +.field-actions { + display: flex; + justify-content: center; + align-items: center; + padding: 18px 0 22px 0; +} + +.field-actions input[type="button"], .field-actions input[type="submit"] { + background: var(--accent); + color: var(--accent-text); + border: none; + padding: 11px 40px; + font-size: 14px; + font-weight: 700; + letter-spacing: 0.02em; + border-radius: 999px; + box-shadow: 0 2px 6px rgba(15,23,42,0.16), 0 8px 20px -8px rgba(15,23,42,0.28); + cursor: pointer; +} + +.field-actions input[type="button"]:active, .field-actions input[type="submit"]:active { + filter: brightness(0.97); +} + +.footer { + background: transparent; + text-decoration: none; + color: #6b7280; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + font-size: 10.5px; + text-align: left; + padding: 14px 16px 20px 16px; + border-top: 1px solid rgba(0,0,0,0.07); + clear: both; +} + +.footer a { + color: var(--accent) !important; +} + +#tail { + height: 450px; + width: 100%; + overflow-y: scroll; + overflow-x: scroll; + color: #3ce87a; + background: #10141a; + border-radius: 8px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + box-sizing: border-box; +} + +#tail::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +#tail::-webkit-scrollbar-track { + background: #10141a; +} + +#tail::-webkit-scrollbar-thumb { + background: rgba(60, 232, 122, 0.35); + border-radius: 6px; +} + +table { + vertical-align: middle; + text-align: center; + empty-cells: show; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; + border-collapse: collapse; + border: none; + text-decoration: none; + color: #ffffff; + background: transparent; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + width: 100%; + white-space: nowrap; +} + +table th { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-shadow: none; + text-decoration: none; + background: transparent; + color: var(--content-text); + text-transform: uppercase; + font-size: 10.5px; + font-weight: 700; + letter-spacing: 0.03em; + padding: 9px 10px; + border: none; + border-bottom: 2px solid var(--accent); +} + +table tr:nth-child(even) { + background: var(--table-even); +} + +table tr:nth-child(odd) { + background: var(--table-odd); +} + +table td { + color: var(--content-text); + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + text-decoration: none; + padding: 7px 10px; + border: none; + border-bottom: 1px solid var(--card-border); + overflow-x: hidden; +} + +table tr:last-child td { + border-bottom: none; +} + +body { + background: var(--page-bg); + color: var(--content-text); +} + +a { + text-decoration:none; +} + +a:link, a:visited { + text-decoration: none; + color: var(--accent); + font-weight: normal; + transition: color 0.15s ease; +} + +a:hover { + color: var(--accent-dark); + text-decoration: underline; +} + +a.tooltip, a.tooltip:link, a.tooltip:visited, a.tooltip:active { + text-decoration: none; + position: relative; + color: #FFFFFF; +} + +a.tooltip:hover { + text-shadow: none; + text-decoration: none; + color: #FFFFFF; + background: transparent; +} + +a.tooltip span { + text-shadow: none; + text-decoration: none; + display: none; +} + +a.tooltip:hover span { + text-shadow: none; + text-decoration: none; + display: block; + position: absolute; + top: 20px; + left: 0; + width: 200px; + z-index: 100; + color: #000000; + border: none; + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); + background: #f7f7f7; + font: 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + overflow: hidden; +} + +a.tooltip span b { + text-shadow: none; + text-decoration: none; + display: block; + color: #000000; + margin: 0; + padding: 4px 8px; + font-size: 12px; + font-weight: bold; + border: 0px; + border-bottom: 1px solid rgba(0,0,0,0.15); + background: #e2e2e2; +} + +a.tooltip2, a.tooltip2:link, a.tooltip2:visited, a.tooltip2:active { + text-shadow: none; + text-decoration: none; + position: relative; + font-weight: bold; + color: #000000; +} + +a.tooltip2:hover { + text-shadow: none; + text-decoration: none; + color: #000000; + background: transparent; +} + +a.tooltip2 span { + text-shadow: none; + text-decoration: none; + display: none; +} + +a.tooltip2:hover span { + text-shadow: none; + text-decoration: none; + display: block; + position: absolute; + top: 20px; + left: 0; + width: 200px; + z-index: 100; + color: #000000; + border: none; + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); + background: #f7f7f7; + font: 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + overflow: hidden; +} + +a.tooltip2 span b { + text-shadow: none; + text-decoration: none; + display: block; + color: #000000; + margin: 0; + padding: 4px 8px; + font-size: 12px; + font-weight: bold; + border: 0px; + border-bottom: 1px solid rgba(0,0,0,0.15); + background: #e2e2e2; +} + +ul { + padding: 5px; + margin: 10px 0; + list-style: none; + float: left; +} + +ul li { + float: left; + display: inline; /*For ignore double margin in IE6*/ + margin: 0 10px; +} + +ul li a { + text-decoration: none; + float:left; + color: #999; + cursor: pointer; + font: 900 14px/22px -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + transition: color 0.15s ease; +} + +ul li a span { + margin: 0 10px 0 -10px; + padding: 1px 8px 5px 18px; + position: relative; /*To fix IE6 problem (not displaying)*/ + float:left; +} + +ul.mmenu li a.current, ul.mmenu li a:hover { + background: url(/images/buttonbg.png) no-repeat top right; + color: #0d5f83; +} + +ul.mmenu li a.current span, ul.mmenu li a:hover span { + background: url(/images/buttonbg.png) no-repeat top left; +} + +h1 { + text-shadow: 1px 1px 2px rgba(0,0,0,0.35); + text-align: center; +} + +/* CSS Toggle Code here */ +.toggle { + position: absolute; + margin-left: -9999px; + visibility: hidden; +} + +.toggle + label { + display: block; + position: relative; + cursor: pointer; + outline: none; +} + +input.toggle-round-flat + label { + padding: 1px; + width: 33px; + height: 18px; + background-color: #dddddd; + border-radius: 10px; + transition: background 0.4s; +} + +input.toggle-round-flat + label:before, +input.toggle-round-flat + label:after { + display: block; + position: absolute; + content: ""; +} + +input.toggle-round-flat + label:before { + top: 1px; + left: 1px; + bottom: 1px; + right: 1px; + background-color: #fff; + border-radius: 10px; + transition: background 0.4s; +} + +input.toggle-round-flat + label:after { + top: 2px; + left: 2px; + bottom: 2px; + width: 16px; + background-color: #dddddd; + border-radius: 12px; + transition: margin 0.4s, background 0.4s; +} + +input.toggle-round-flat:checked + label { + background-color: var(--accent); +} + +input.toggle-round-flat:checked + label:after { + margin-left: 14px; + background-color: var(--accent); +} + +/* Gentle, geometry-neutral polish for form controls (no size/layout changes) */ +input[type="text"], input[type="password"], input[type="number"], input[type="email"], select, textarea { + border-radius: 4px; + transition: box-shadow 0.15s ease, border-color 0.15s ease; +} + +input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus, input[type="email"]:focus, select:focus, textarea:focus { + outline: none; + box-shadow: 0 0 0 3px rgba(79,70,229,0.18); + border-color: var(--accent); +} + +input[type="submit"], input[type="button"], button { + cursor: pointer; + border-radius: 4px; + transition: filter 0.15s ease, box-shadow 0.15s ease; +} + +input[type="submit"]:hover, input[type="button"]:hover, button:hover { + filter: brightness(1.06); + box-shadow: 0 1px 6px rgba(0,0,0,0.25); +} + +/* Tame Firefox Buttons */ +@-moz-document url-prefix() { + select, + input { + margin : 0; + padding : 0; + border-width : 1px; + font : 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + } + input[type="button"], button, input[type="submit"] { + padding : 0px 3px 0px 3px; + border-radius : 3px 3px 3px 3px; + -moz-border-radius : 3px 3px 3px 3px; + } +} + +/* nice-select dropdowns */ +.nice-select.small, .nice-select-dropdown li.option { + height: 24px !important; + min-height: 24px !important; + line-height: 24px !important; +} +.nice-select.small ul li:nth-of-type(2) { + clear: both; +} diff --git a/admin/css/pistar-css.php b/admin/css/pistar-css.php new file mode 100644 index 0000000..fc13710 --- /dev/null +++ b/admin/css/pistar-css.php @@ -0,0 +1,1104 @@ + +:root { + --page-bg: #; + --content-bg: #; + --accent: #; + --accent-dark: #; + --accent-light: #; + --accent-text: #; + --banner-drop: #; + --table-head-drop: #; + --content-text: #; + --table-even: #; + --table-odd: #; + --sidebar-width: 250px; + --nav-width: 226px; + --sidebar-bg: #111827; + --sidebar-bg-2: #0b1120; + --sidebar-text: #cbd5e1; + --sidebar-text-dim: #94a3b8; + --sidebar-card-bg: rgba(255,255,255,0.05); + --sidebar-card-strong-bg: rgba(255,255,255,0.09); + --radius: 12px; + --radius-sm: 8px; + --card-border: rgba(15,23,42,0.07); + --shadow-card: 0 1px 2px rgba(15,23,42,0.04), 0 10px 28px -14px rgba(15,23,42,0.16); +} + +* { + -webkit-font-smoothing: antialiased; +} + +html, body { + margin: 0; + padding: 0; +} + +body, font { + font: 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + color: #ffffff; +} + +body { + background: var(--page-bg); + color: var(--content-text); +} + +/* Outer shell: the sidebar (.header) is fixed, everything else lives in this column */ +.container { + width: auto; + margin: 0 0 0 var(--sidebar-width); + min-height: 100vh; + text-align: left; + background: var(--page-bg); + box-shadow: none; + border-radius: 0; + overflow: visible; +} + +/* The left-hand navigation rail. Same markup as before (title + link list), + just presented as a fixed vertical sidebar instead of a top banner. */ +.header { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: var(--sidebar-width); + background: linear-gradient(180deg, var(--sidebar-bg), var(--sidebar-bg-2)); + color: var(--sidebar-text); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + padding: 22px 16px 16px 16px; + overflow-y: auto; + z-index: 200; + display: flex; + flex-direction: column; + box-sizing: border-box; +} + +.header h1 { + font-size: 1.15em; + line-height: 1.3; + color: #ffffff; + text-shadow: none; + text-align: left; + margin: 0 0 4px 0; + padding: 0; + font-weight: 700; +} + +.header > div[style*="font-size: 8px"] { + float: none !important; + text-align: left !important; + color: var(--sidebar-text-dim) !important; + font-size: 10.5px !important; + padding: 0 !important; + margin: 0 0 14px 0; +} + +.header p { + /* The historical pipe-separated link list. Collapsing the literal " | " + separators to zero size turns it into a clean vertical nav without + touching the markup that generates it. */ + font-size: 0; + margin: 6px 0; + padding: 0; + text-align: left !important; + display: flex; + flex-direction: column; + gap: 2px; +} + +.header p a, .header p a:link, .header p a:visited { + display: block; + font-size: 13px; + font-weight: 500; + color: var(--sidebar-text) !important; + padding: 9px 10px; + border-radius: 8px; + transition: background 0.15s ease, color 0.15s ease; +} + +.header p a:hover { + background: rgba(255,255,255,0.08); + color: #ffffff !important; +} + +.header p a.active { + background: var(--accent); + color: var(--accent-text) !important; + font-weight: 700; +} + +.header p b { + font-size: 11px; + color: var(--sidebar-text-dim); + display: block; + margin: 10px 0 2px 2px; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +/* Second half of the sidebar: live status widgets (Modes/Network/Radio Info). + Same dark surface as .header so the two columns read as one continuous + rail, even though .nav scrolls with the page instead of staying fixed. */ +/* Wraps .nav + .content so both stretch to the same height - without this, + the dark .nav background only reached as far down as its own widgets and + left a visible step where the fixed .header strip kept going but .nav + stopped short. */ +.dashboard-row { + display: flex; + align-items: stretch; +} + +.nav { + flex: none; + display: flex; + flex-direction: column; + justify-content: center; + box-sizing: border-box; + margin: 0; + padding: 20px 14px; + width: var(--nav-width); + background: linear-gradient(180deg, var(--sidebar-bg), var(--sidebar-bg-2)); + font-weight: normal; +} + +.nav table { + width: 100%; + margin: 0 0 16px 0; + border-collapse: separate; + border-spacing: 4px; + table-layout: fixed; + white-space: normal; +} + +/* Section titles ("Modes Enabled", "Radio Info", "DMR Master"...) */ +.nav table th[colspan] { + background: transparent; + color: var(--sidebar-text-dim); + text-align: left; + text-transform: uppercase; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.06em; + padding: 12px 2px 6px 2px; + border: none; +} + +.nav table:first-child th[colspan] { + padding-top: 0; +} + +/* Field-label cells (Trx / Tx / Rx / RPT1 / DMR ID ...) */ +.nav table th:not([colspan]) { + background: var(--sidebar-card-bg); + color: var(--sidebar-text-dim); + text-align: left; + font-size: 10.5px; + font-weight: 700; + letter-spacing: 0.02em; + padding: 7px 8px; + border: none; + border-radius: var(--radius-sm); + width: 30%; +} + +/* Value / status cells. Anything with an inline background (status colour + pills from showMode()/repeaterinfo.php) keeps that colour untouched - + we only add shape. Explicit inline white backgrounds are swapped for a + theme-matching dark surface so they don't glow against the sidebar. */ +.nav table td { + color: var(--sidebar-text); + background: var(--sidebar-card-bg); + font-size: 11px; + font-weight: 600; + padding: 7px 8px; + border: none; + border-radius: var(--radius-sm); + text-overflow: ellipsis; + overflow: hidden; +} + +.nav table td[style*="fff"] { + background: var(--sidebar-card-strong-bg) !important; + color: var(--sidebar-text) !important; +} + +.nav table tr:nth-child(even), +.nav table tr:nth-child(odd) { + background: transparent; +} + +.nav table a { color: #ffffff; font-weight: 700; } +.nav table a:hover { color: var(--accent-light); } + +.content { + flex: 1 1 auto; + min-width: 0; + margin: 0 0 0 20px; + padding: 24px 28px 28px 28px; + color: var(--content-text); + background: var(--page-bg); + text-align: left; +} + +.contentwide { + padding: 24px 28px; + color: var(--content-text); + background: var(--page-bg); + text-align: center; +} + +.contentwide h2 { + color: var(--content-text); + font: 600 1.15em -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + padding: 0 0 10px 14px; + margin: 32px 0 14px 0; + border-left: 4px solid var(--accent); + border-bottom: 1px solid rgba(0,0,0,0.08); +} + +.contentwide h2:first-child { + margin-top: 0; +} + +.contentwide h3 { + color: var(--content-text); + font: 600 0.95em -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + margin: 20px 0 8px 2px; +} + +.contentwide h3:first-of-type { + margin-top: 4px; +} + +/* Usage meter (RAM/disk bars on the SysInfo page) */ +.meter { + position: relative; + width: 100%; + max-width: 420px; + height: 20px; + background: var(--page-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 10px; + overflow: hidden; +} + +.meter-bar { + height: 100%; + background: linear-gradient(90deg, var(--accent-light), var(--accent)); +} + +.meter-label { + position: absolute; + top: 0; + left: 10px; + line-height: 20px; + font-size: 11.5px; + font-weight: 600; + color: var(--content-text); +} + +/* Inline "Alert: ..." banners used across the dashboard (config warnings etc.) */ +.alert-banner-table { + margin: 0 0 16px 0 !important; + width: 100% !important; +} + +.alert-banner-table, .alert-banner-table tr { + background: transparent !important; +} + +.alert-cell { + text-align: left !important; + border-radius: 8px; + padding: 12px 16px !important; + font-weight: 500; + border: 1px solid transparent; +} + +.alert-warning { + background: #fffbeb; + color: #92400e; + border-color: #fde68a; +} + +.alert-danger { + background: #fef2f2; + color: #b91c1c; + border-color: #fecaca; +} + +.alert-warning a, .alert-danger a { + color: inherit; + text-decoration: underline; +} + +.footer { + background: transparent; + text-decoration: none; + color: #6b7280; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + font-size: 10.5px; + text-align: left; + padding: 16px 28px 24px 28px; + border-top: 1px solid rgba(0,0,0,0.07); + clear: both; +} + +.footer a { + color: var(--accent) !important; +} + +/* Modern settings form: replaces the old table-based "Setting | Value" rows. + .settings-card wraps a section's fields; .field-row is one label+control pair. */ +.settings-card { + background: var(--content-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0,0,0,0.04); + padding: 4px 20px; + margin: 0 0 28px 0; + text-align: left; +} + +/* Legacy fragments open with a bare Title before their content - + give it the same accent-dot heading treatment as the dashboard cards, + wherever it shows up, without having to touch every include site. */ +.settings-card > b:first-child { + display: flex; + align-items: center; + gap: 9px; + font-size: 15px; + font-weight: 700; + color: var(--content-text); + margin: 16px 0 14px 0; + padding-bottom: 12px; + border-bottom: 1px solid var(--card-border); +} + +.settings-card > b:first-child::before { + content: ""; + width: 9px; + height: 9px; + border-radius: 3px; + background: var(--accent); + flex: none; +} + +.field-row { + display: flex; + align-items: center; + flex-wrap: wrap; + column-gap: 24px; + row-gap: 6px; + padding: 13px 0; + border-bottom: 1px solid rgba(0,0,0,0.06); +} + +.field-row:last-child { + border-bottom: none; +} + +.field-label { + flex: 0 0 260px; + max-width: 260px; + font-weight: 500; + font-size: 13px; + color: var(--content-text); + text-align: left; +} + +.field-control { + flex: 1 1 320px; + text-align: left; + color: var(--content-text); + font-size: 13px; +} + +.field-control input[type="text"], .field-control input[type="password"], .field-control input[type="number"] { + padding: 5px 8px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-control select { + padding: 4px 6px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-actions { + display: flex; + justify-content: center; + align-items: center; + padding: 20px 0 24px 0; +} + +.field-actions input[type="button"], .field-actions input[type="submit"] { + background: var(--accent); + color: var(--accent-text); + border: none; + padding: 12px 48px; + font-size: 14px; + font-weight: 700; + letter-spacing: 0.02em; + border-radius: 999px; + box-shadow: 0 2px 6px rgba(15,23,42,0.16), 0 8px 20px -8px rgba(15,23,42,0.28); + cursor: pointer; + transition: filter 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease; +} + +.field-actions input[type="button"]:hover, .field-actions input[type="submit"]:hover { + filter: brightness(1.08); + box-shadow: 0 4px 10px rgba(15,23,42,0.2), 0 10px 24px -8px rgba(15,23,42,0.32); + transform: translateY(-1px); +} + +.field-actions input[type="button"]:active, .field-actions input[type="submit"]:active { + transform: translateY(0); + filter: brightness(0.97); +} + +.field-note { + font-weight: 400; + font-size: 12.5px; + color: #6b7280; + flex: 1 1 100% !important; + max-width: none !important; +} + +/* Big icon action buttons (power page, reboot/shutdown) */ +.action-tiles { + display: flex; + gap: 16px; + padding: 20px; +} + +.action-tile { + flex: 1 1 0; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + padding: 24px 16px; + background: var(--page-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 10px; + cursor: pointer; + font: 500 14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + color: var(--content-text); + transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease; +} + +.action-tile:hover { + border-color: var(--accent); + box-shadow: 0 4px 12px rgba(0,0,0,0.08); + transform: translateY(-1px); +} + +.action-tile img { + width: 48px; + height: 48px; +} + +.action-tile-upload { + cursor: default; +} + +.action-tile-upload input[type="file"] { + max-width: 100%; + font-size: 12px; +} + +.action-tile-upload button { + margin-top: 4px; +} + +/* Calibration tool control panels */ +.cal-grid { + display: flex; + flex-wrap: wrap; + gap: 16px; + align-items: flex-start; +} + +.cal-panel { + flex: 1 1 220px; + margin: 0; +} + +.cal-panel h3 { + margin-top: 0; +} + +.cal-panel table { + width: 100%; +} + +.cal-btn-row { + display: flex; + align-items: center; + gap: 10px; + padding: 6px 0; +} + +/* Raw config-file editors (expert "Full Edit" pages) */ +.raw-editor { + width: 100%; + min-height: 480px; + box-sizing: border-box; + background: #10141a; + color: #d1d5db; + border: 1px solid rgba(0,0,0,0.15); + border-radius: 8px; + padding: 12px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + font-size: 12.5px; + line-height: 1.5; +} + +.power-status { + background: #10141a; + color: #3ce87a; + border-radius: 8px; + padding: 20px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + line-height: 1.7; +} + +/* Positional fallback for field-rows whose cells weren't given explicit + .field-label/.field-control classes (converted straight from table rows): + first direct child reads as the label, the rest as the control area. */ +.field-row > div:first-child { + flex: 0 0 260px; + max-width: 260px; + font-weight: 500; + font-size: 13px; + text-align: left; +} + +.field-row > div:not(:first-child) { + flex: 1 1 280px; + text-align: left; + font-size: 13px; +} + +.field-row input[type="text"], .field-row input[type="password"], .field-row input[type="number"] { + padding: 5px 8px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-row select { + padding: 4px 6px; + border: 1px solid rgba(0,0,0,0.18); +} + +@media (max-width: 780px) { + .field-row { + flex-direction: column; + align-items: flex-start; + } + .field-label, .field-row > div:first-child { + flex: 0 0 auto; + max-width: none; + } +} + +#tail { + height: 450px; + width: 100%; + max-width: 805px; + overflow-y: scroll; + overflow-x: scroll; + color: #3ce87a; + background: #10141a; + border-radius: 8px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + box-sizing: border-box; +} + +#tail::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +#tail::-webkit-scrollbar-track { + background: #10141a; +} + +#tail::-webkit-scrollbar-thumb { + background: rgba(60, 232, 122, 0.35); + border-radius: 6px; +} + +/* Dashboard widget panels: the Gateway/Local RF Activity tables (and the + POCSAG Pages list) get promoted from bare Title+ into real + cards, without touching the PHP that generates them. */ +#lastHerd, #localTxs, #Pages, #sysInfo, +#refLinks, #cssConnects, #lh, #localTx, #bmConnects, #tgifConnects { + width: 100%; + margin: 0 0 20px 0; + background: var(--content-bg); + border: 1px solid var(--card-border); + border-radius: var(--radius); + box-shadow: var(--shadow-card); + padding: 18px 22px 22px 22px; + box-sizing: border-box; + overflow-x: auto; +} + +#lastHerd > b, #localTxs > b, #Pages > b, #sysInfo > b, +#refLinks > b, #cssConnects > b, #lh > b, #localTx > b, #bmConnects > b, #tgifConnects > b { + display: flex; + align-items: center; + gap: 9px; + font-size: 15px; + font-weight: 700; + color: var(--content-text); + margin: 0 0 14px 0; + padding-bottom: 12px; + border-bottom: 1px solid var(--card-border); +} + +#lastHerd > b::before, #localTxs > b::before, #Pages > b::before, #sysInfo > b::before, +#refLinks > b::before, #cssConnects > b::before, #lh > b::before, #localTx > b::before, #bmConnects > b::before, #tgifConnects > b::before { + content: ""; + width: 9px; + height: 9px; + border-radius: 3px; + background: var(--accent); + flex: none; +} + +table { + vertical-align: middle; + text-align: center; + empty-cells: show; + padding-left: 0px; + padding-right: 0px; + padding-top: 0px; + padding-bottom: 0px; + border-collapse: collapse; + border: none; + text-decoration: none; + color: #ffffff; + background: transparent; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + width: 100%; + white-space: nowrap; +} + +table th { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-shadow: none; + text-decoration: none; + background: transparent; + color: var(--content-text); + text-transform: uppercase; + font-size: 11px; + font-weight: 700; + letter-spacing: 0.04em; + padding: 10px 12px; + border: none; + border-bottom: 2px solid var(--accent); +} + +table tr:nth-child(even) { + background: var(--table-even); +} + +table tr:nth-child(odd) { + background: var(--table-odd); +} + +table td { + color: var(--content-text); + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + text-decoration: none; + padding: 8px 12px; + border: none; + border-bottom: 1px solid var(--card-border); +} + +table tr:last-child td { + border-bottom: none; +} + +.content table tr:hover td, .contentwide table tr:hover td { + background: rgba(15,23,42,0.045); +} + +a { + text-decoration:none; +} + +a:link, a:visited { + text-decoration: none; + color: var(--accent); + font-weight: normal; + transition: color 0.15s ease; +} + +a:hover { + color: var(--accent-dark); + text-decoration: underline; +} + +a.tooltip, a.tooltip:link, a.tooltip:visited, a.tooltip:active { + text-decoration: none; + position: relative; + color: #FFFFFF; +} + +a.tooltip:hover { + text-shadow: none; + text-decoration: none; + color: #FFFFFF; + background: transparent; +} + +a.tooltip span { + text-shadow: none; + text-decoration: none; + display: none; +} + +a.tooltip:hover span { + text-shadow: none; + text-decoration: none; + display: block; + position: absolute; + top: 20px; + left: 0; + z-index: 100; + color: #000000; + border: none; + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); + background: #f7f7f7; + font: 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + white-space: nowrap; + overflow: hidden; +} + +th:last-child a.tooltip:hover span { + left: auto; + right: 0; +} + +a.tooltip span b { + text-shadow: none; + text-decoration: none; + display: block; + color: #000000; + margin: 0; + padding: 4px 8px; + font-size: 12px; + font-weight: bold; + border: 0px; + border-bottom: 1px solid rgba(0,0,0,0.15); + background: #e2e2e2; +} + +a.tooltip2, a.tooltip2:link, a.tooltip2:visited, a.tooltip2:active { + text-shadow: none; + text-decoration: none; + position: relative; + font-weight: bold; + color: #000000; +} + +a.tooltip2:hover { + text-shadow: none; + text-decoration: none; + color: #000000; + background: transparent; +} + +a.tooltip2 span { + text-shadow: none; + text-decoration: none; + display: none; +} + +a.tooltip2:hover span { + text-shadow: none; + text-decoration: none; + display: block; + position: absolute; + top: 20px; + left: 0; + width: 202px; + z-index: 100; + color: #000000; + border: none; + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); + background: #f7f7f7; + font: 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + white-space: normal; + overflow: hidden; +} + +a.tooltip2 span b { + text-shadow: none; + text-decoration: none; + display: block; + color: #000000; + margin: 0; + padding: 4px 8px; + font-size: 12px; + font-weight: bold; + border: 0px; + border-bottom: 1px solid rgba(0,0,0,0.15); + background: #e2e2e2; +} + +ul { + padding: 5px; + margin: 10px 0; + list-style: none; + float: left; +} + +ul li { + float: left; + display: inline; /*For ignore double margin in IE6*/ + margin: 0 10px; +} + +ul li a { + text-decoration: none; + float:left; + color: #999; + cursor: pointer; + font: 900 14px/22px -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + transition: color 0.15s ease; +} + +ul li a span { + margin: 0 10px 0 -10px; + padding: 1px 8px 5px 18px; + position: relative; /*To fix IE6 problem (not displaying)*/ + float:left; +} + +ul.mmenu li a.current, ul.mmenu li a:hover { + background: url(/images/buttonbg.png) no-repeat top right; + color: #0d5f83; +} + +ul.mmenu li a.current span, ul.mmenu li a:hover span { + background: url(/images/buttonbg.png) no-repeat top left; +} + +h1 { + text-shadow: 1px 1px 2px rgba(0,0,0,0.35); + text-align: center; +} + +/* CSS Toggle Code here */ +.toggle { + position: absolute; + margin-left: -9999px; + visibility: hidden; +} + +.toggle + label { + display: block; + position: relative; + cursor: pointer; + outline: none; +} + +input.toggle-round-flat + label { + padding: 1px; + width: 33px; + height: 18px; + background-color: #dddddd; + border-radius: 10px; + transition: background 0.4s; +} + +input.toggle-round-flat + label:before, +input.toggle-round-flat + label:after { + display: block; + position: absolute; + content: ""; +} + +input.toggle-round-flat + label:before { + top: 1px; + left: 1px; + bottom: 1px; + right: 1px; + background-color: #fff; + border-radius: 10px; + transition: background 0.4s; +} + +input.toggle-round-flat + label:after { + top: 2px; + left: 2px; + bottom: 2px; + width: 16px; + background-color: #dddddd; + border-radius: 12px; + transition: margin 0.4s, background 0.4s; +} + +input.toggle-round-flat:checked + label { + background-color: var(--accent); +} + +input.toggle-round-flat:checked + label:after { + margin-left: 14px; + background-color: var(--accent); +} + +/* Gentle, geometry-neutral polish for form controls (no size/layout changes) */ +input[type="text"], input[type="password"], input[type="number"], input[type="email"], select, textarea { + border-radius: 4px; + transition: box-shadow 0.15s ease, border-color 0.15s ease; +} + +input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus, input[type="email"]:focus, select:focus, textarea:focus { + outline: none; + box-shadow: 0 0 0 3px rgba(79,70,229,0.18); + border-color: var(--accent); +} + +input[type="submit"], input[type="button"], button { + cursor: pointer; + border-radius: 4px; + transition: filter 0.15s ease, box-shadow 0.15s ease; +} + +input[type="submit"]:hover, input[type="button"]:hover, button:hover { + filter: brightness(1.06); + box-shadow: 0 1px 6px rgba(0,0,0,0.25); +} + +/* Tame Firefox Buttons */ +@-moz-document url-prefix() { + select, + input { + margin : 0; + padding : 0; + border-width : 1px; + font : 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + } + input[type="button"], button, input[type="submit"] { + padding : 0px 3px 0px 3px; + border-radius : 3px 3px 3px 3px; + -moz-border-radius : 3px 3px 3px 3px; + } +} + +/* nice-select dropdowns */ +.nice-select.small, .nice-select-dropdown li.option { + height: 24px !important; + min-height: 24px !important; + line-height: 24px !important; +} +.nice-select.small ul li:nth-of-type(2) { + clear: both; +} + +/* Collapse the fixed sidebar into a top bar on narrow viewports */ +@media (max-width: 780px) { + .header { + position: static; + width: auto; + height: auto; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + } + .header p { + flex-direction: row; + flex-wrap: wrap; + } + .container { + margin-left: 0; + } + .dashboard-row { + flex-direction: column; + } + .nav { + width: auto; + } + .content { + margin-left: 0; + } +} + +/* Aria CSS Here +[role="checkbox"] { + padding:5px; +} + +[aria-checked="true"]::before { + content: "[x]"; +} + +[aria-checked="false"]::before { + content: "[ ]"; +} +*/ diff --git a/admin/download_modem_log.php b/admin/download_modem_log.php index 835c6d9..2f6fab6 100644 --- a/admin/download_modem_log.php +++ b/admin/download_modem_log.php @@ -1,63 +1,50 @@ diff --git a/admin/dstarrepeater b/admin/dstarrepeater deleted file mode 100644 index b3191ee..0000000 --- a/admin/dstarrepeater +++ /dev/null @@ -1 +0,0 @@ -../dstarrepeater/ \ No newline at end of file diff --git a/admin/dstarrepeater/active_reflector_links.php b/admin/dstarrepeater/active_reflector_links.php new file mode 100644 index 0000000..ea1faa8 --- /dev/null +++ b/admin/dstarrepeater/active_reflector_links.php @@ -0,0 +1,187 @@ + 0) + $configs[$key] = $value; + } + +} +$progname = basename($_SERVER['SCRIPT_FILENAME'],".php"); +$rev="20141101"; +$MYCALL=strtoupper($callsign); +?> + +
+ + + + + + + + + + + + +"Never",1=>"Fixed",2=>"5min",3=>"10min",4=>"15min",5=>"20min",6=>"25min",7=>"30min",8=>"60min",9=>"90min",10=>"120min",11=>"180min",12=>" "); + $ci = 0; + $tr = 0; + for($i = 1;$i < 5; $i++){ + $param="repeaterBand" . $i; + if((isset($configs[$param])) && strlen($configs[$param]) == 1) { + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + $tr = 1; + $module = $configs[$param]; + $rcall = sprintf("%-7.7s%-1.1s",$MYCALL,$module); + $param="repeaterCall" . $i; + if(isset($configs[$param])) { $rptrcall=sprintf("%-7.7s%-1.1s",$configs[$param],$module); } else { $rptrcall = $rcall;} + print ""; + $param="reflector" . $i; + if(isset($configs[$param])) { print ""; } else { print "";} + $param="atStartup" . $i; + if($configs[$param] == 1){print ""; } else { print ""; } + $param="reconnect" . $i; + if(isset($configs[$param])) { $t = $configs[$param]; } else { $t = 0; } + if($t > 12){ $t = 12; } + print ""; + $j=0; + if ($linkLog = fopen($linkLogPath,'r')) { + while ($linkLine = fgets($linkLog)) { + //$statimg = ""; + $statimg = "Down"; + $linkDate = " "; + $protocol = " "; + $linkType = " "; + $linkRptr = " "; + $linkRefl = " "; +// Reflector-Link, sample: +// 2011-09-22 02:15:06: DExtra link - Type: Repeater Rptr: DB0LJ B Refl: XRF023 A Dir: Outgoing +// 2012-10-12 17:15:45: DCS link - Type: Repeater Rptr: DB0LJ B Refl: DCS001 L Dir: Outgoing +// 2012-10-12 17:56:10: DCS link - Type: Repeater Rptr: DB0RPL B Refl: DCS015 B Dir: Outgoing + if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*Rptr: (.{8}).*Refl: (.{8}).*Dir: Outgoing$/',$linkLine,$linx) > 0){ + $statimg = "Up"; + $linkDate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); + $protocol = $linx[2][0]; + $linkType = $linx[3][0]; + $linkRptr = $linx[4][0]; + $linkRefl = $linx[5][0]; + if($linkRptr == $rptrcall){ + print ""; + print ""; + print ""; + print ""; + $utc_time = $linkDate; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + print ""; + print "\n"; + $tr = 0; + } + } + } + fclose($linkLog); + } + + if ($tr == 1){ + print"\n"; + } +// 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 +// 2012-05-08 21:16:31: DExtra link - Type: Repeater Rptr: DB0LJ A Refl: DB0MYK B Dir: Incoming +// 2012-05-08 21:16:31: DPlus link - Type: Dongle User: W1CDG H Dir: Incoming + if ($linkLog = fopen($linkLogPath,'r')) { + while ($linkLine = fgets($linkLog)) { + $statimg = "Down"; + $linkDate = " "; + $protocol = " "; + $linkType = " "; + $linkRptr = " "; + $linkRefl = " "; + if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*Rptr: (.{8}).*Refl: (.{8}).*Dir: Incoming$/',$linkLine,$linx) > 0){ + $statimg = "Up"; + $linkDate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); + $protocol = $linx[2][0]; + $linkType = $linx[3][0]; + $linkRptr = $linx[4][0]; + $linkRefl = $linx[5][0]; + if($linkRptr == $rptrcall){ + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + $utc_time = $linkDate; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + print ""; + print "\n"; + //$tr = 0; + } + } + } + fclose($linkLog); + } +// 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 +// 2012-05-08 21:16:31: DExtra link - Type: Repeater Rptr: DB0LJ A Refl: DB0MYK B Dir: Incoming +// 2012-05-08 21:16:31: DPlus link - Type: Dongle User: W1CDG H Dir: Incoming + if ($linkLog = fopen($linkLogPath,'r')) { + while ($linkLine = fgets($linkLog)) { + $statimg = "Down"; + $linkDate = " "; + $protocol = " "; + $linkType = " "; + $linkRptr = " "; + $linkRefl = " "; + if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*User: (.[^\s]+).*Dir: Incoming$/',$linkLine,$linx) > 0){ + $statimg = "Up"; + $linkDate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); + $protocol = $linx[2][0]; + $linkType = $linx[3][0]; + $linkRptr = $linx[4][0]; + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + $utc_time = $linkDate; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + print ""; + print "\n"; + } + } + fclose($linkLog); + } + // End + } + } +?> + +
RadioRadio ModuleDefaultDefault Link DestinationAutoAutoLink- green: enabled
- red: disabled
TimerReset/Restart TimerLinkLink-Status- green: enabled
- red: disabled
Linked toLinked DestinationModeMode or Protocol usedDirectionDirectionIncoming or OutgoingLast Change ()Timestamp of last changeTime of last change in time zone
".str_replace(' ', ' ', substr($rptrcall,0,8))."".str_replace(' ', ' ', substr($configs[$param],0,8))." AutoNo$tot[$t]$statimg".str_replace(' ', ' ', substr($linkRefl,0,8))."$protocolOutgoing$local_time
DownNone----------
".str_replace(' ', ' ', substr($rptrcall,0,8))."   $statimg".str_replace(' ', ' ', substr($linkRefl,0,8))."$protocolIncoming$local_time
".str_replace(' ', ' ', substr($rptrcall,0,8))."   $statimg".str_replace(' ', ' ', substr($linkRptr,0,8))."$protocolIncoming$local_time
diff --git a/admin/dstarrepeater/active_starnet_groups.php b/admin/dstarrepeater/active_starnet_groups.php new file mode 100644 index 0000000..102c01e --- /dev/null +++ b/admin/dstarrepeater/active_starnet_groups.php @@ -0,0 +1,125 @@ + 0) + $configs[$key] = $value; + } + +} +$progname = basename($_SERVER['SCRIPT_FILENAME'],".php"); +$rev="20141101"; +$MYCALL=strtoupper($callsign); +?> + + + + + + + + + + 1) { $ci = 0; } + print ""; + print ""; + $param="starNetLogoff" . $i; + if(isset($configs[$param])){ $output = str_replace(' ', ' ', substr($configs[$param],0,8)); print "";} else { print"";} + $param="starNetInfo" . $i; + if(isset($configs[$param])){ print "";} else { print"";} + $param="starNetUserTimeout" . $i; + if(isset($configs[$param])){ print "";} else { print"";} + $param="starNetGroupTimeout" . $i; + if(isset($configs[$param])){ print "";} else { print"";} + print "\n"; + } + } +?> +
Starnet CallsignStarnet Logoff CallsignInfotextUser TimeOut (min)inactivity time after which a user will be disconnectedGroup TimeOut (min)inactivity time after which the group will be disconnected
".str_replace(' ', ' ', substr($gname,0,8))."$output $configs[$param] $configs[$param] $configs[$param] 

+ += 1) { + + echo "".$lang['active_starnet_members']."\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + + $ci = 0; + $ulist = array(); + $glist = array(); + for($i = 1;$i < 6; $i++){ + if(isset($groupsx[$i])){ + $glist = $groupsx[$i]; + foreach ($glist as $gcall => $ulist){ + foreach ($ulist as $ucall => $ulogin){ + $ci++; + if($ci > 1) { $ci = 0; } + $ulogin = date("d-M-Y H:i:s", strtotime(substr($ulogin,0,19))); + $utc_time = $ulogin; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + $groupz = str_replace(' ', ' ', substr($gcall,0,8)); + $ucall = str_replace(' ', '', substr($ucall,0,8)); + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + } + } + } + echo "
".$lang['time']." (".date('T').")Time of Login".$lang['group']."Starnet Callsign".$lang['callsign']."Callsign
$local_time$groupz$ucall
\n
\n"; + } + +?> diff --git a/admin/dstarrepeater/css_connections.php b/admin/dstarrepeater/css_connections.php new file mode 100644 index 0000000..8329b9c --- /dev/null +++ b/admin/dstarrepeater/css_connections.php @@ -0,0 +1,76 @@ + 0) + $configs[$key] = $value; + } + +} +$progname = basename($_SERVER['SCRIPT_FILENAME'],".php"); +$rev="20141101"; +$MYCALL=strtoupper($callsign); +?> +=1) { +?> + Active CCS Connections + + + + + + + + + 0){ + $utc_time = $linx[1][0]; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + $linkDate = $local_time; + $linkType = $linx[2][0]; + $linkRptr = $linx[3][0]; + $linkRem = $linx[4][0]; + $linkDir = $linx[5][0]; + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print "\n"; + } + } + fclose($linkLog); + } + + print "
RepeaterCallsign of connected repeaterLinked toActual link statusProtocolProtocolDirectionDirectionincoming or outgoingLast Change ()Timestamp of last change
$linkRptr$linkRemCCS$linkDir$linkDate
\n
\n"; +} + + $stn_is_set = 0; + for($i = 1;$i < 6; $i++){ + $param="starNetCallsign" . $i; + if(isset($configs[$param])) { + $stn_is_set = 1; + break; + } + } + if($stn_is_set > 0){ + include_once $_SERVER['DOCUMENT_ROOT'].'/dstarrepeater/active_starnet_groups.php'; + } +?> diff --git a/admin/dstarrepeater/gateway_software_config.php b/admin/dstarrepeater/gateway_software_config.php new file mode 100644 index 0000000..cb62df0 --- /dev/null +++ b/admin/dstarrepeater/gateway_software_config.php @@ -0,0 +1,20 @@ +
+ + + + + + ON"; } else { print ""; } + if($configs['dcsEnabled'] == 1){print ""; } else { print ""; } + if($configs['dextraEnabled'] == 1){print ""; } else { print ""; } + if($configs['dplusEnabled'] == 1){print ""; } else { print ""; } + if($configs['dratsEnabled'] == 1){print ""; } else { print ""; } + if($configs['infoEnabled'] == 1){print ""; } else { print ""; } + if($configs['ircddbEnabled'] == 1){print ""; } else { print ""; } + if($configs['echoEnabled'] == 1){print ""; } else { print ""; } + if($configs['logEnabled'] == 1){print ""; } else { print ""; } + ?> + +
ircDDB NetworkAPRS HostCCSDCSDExtraDPlusD-RatsInfoircDDBEchoLog
";} ?>OFFONOFFONOFFONOFFONOFFONOFFONOFFONOFFONOFF
+
diff --git a/admin/dstarrepeater/index.php b/admin/dstarrepeater/index.php new file mode 100644 index 0000000..e69de29 diff --git a/admin/dstarrepeater/last_herd.php b/admin/dstarrepeater/last_herd.php new file mode 100644 index 0000000..754ce10 --- /dev/null +++ b/admin/dstarrepeater/last_herd.php @@ -0,0 +1,91 @@ + 0) + $configs[$key] = $value; + } + +} +$progname = basename($_SERVER['SCRIPT_FILENAME'],".php"); +$rev="20141101"; +$MYCALL=strtoupper($callsign); + +// Check if the config file exists +if (file_exists('/etc/pistar-css.ini')) { + // Use the values from the file + $piStarCssFile = '/etc/pistar-css.ini'; + if (fopen($piStarCssFile,'r')) { $piStarCss = parse_ini_file($piStarCssFile, true); } + + // Set the Values from the config file + if (isset($piStarCss['Lookup']['Service'])) { $callsignLookupSvc = $piStarCss['Lookup']['Service']; } // Lookup Service "QRZ" or "RadioID" + else { $callsignLookupSvc = "RadioID"; } // Set the default if its missing // Set the default if its missing +} else { + // Default values + $callsignLookupSvc = "RadioID"; +} + +// Safety net +if (($callsignLookupSvc != "RadioID") && ($callsignLookupSvc != "QRZ")) { $callsignLookupSvc = "RadioID"; } + +// Setup the URL(s) +if ($callsignLookupSvc == "RadioID") { $callsignLookupUrl = "https://database.radioid.net/database/view?callsign="; } +if ($callsignLookupSvc == "QRZ") { $callsignLookupUrl = "https://www.qrz.com/db/"; } + +?> + + + + + + + + + +/tmp/lastheard.log) 2>&1 &'); + $ci = 0; + if ($LastHeardLog = fopen("/tmp/lastheard.log",'r')) { + while ($linkLine = fgets($LastHeardLog)) { + if(preg_match_all('/^(.{19}).*My: (.*).*Your: (.*).*Rpt1: (.*).*Rpt2: (.*).*Flags: (.*)$/',$linkLine,$linx) > 0){ + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + $QSODate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); + $MyCall = str_replace(' ', '', substr($linx[2][0],0,8)); + $MyCallLink = strtok(substr($linx[2][0],0,8), " "); + $MyId = str_replace(' ', '', substr($linx[2][0],9,4)); + $YourCall = str_replace(' ', ' ', substr($linx[3][0],0,8)); + $Rpt1 = str_replace(' ', ' ', substr($linx[4][0],0,8)); + $Rpt2 = str_replace(' ', ' ', substr($linx[5][0],0,8)); + $utc_time = $QSODate; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + print ""; + print ""; } + else { print "
(dPRS)
"; } + print ""; + print ""; + print ""; + print "\n"; + } + } + fclose($LastHeardLog); + } +?> +
()RPT 1RPT 2
$local_time
$MyCall"; + if($MyId) { print "/".$MyId."
$YourCall$Rpt1$Rpt2
diff --git a/admin/dstarrepeater/link_manager.php b/admin/dstarrepeater/link_manager.php new file mode 100644 index 0000000..00ae70f --- /dev/null +++ b/admin/dstarrepeater/link_manager.php @@ -0,0 +1,205 @@ +\nD-Star Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($linkCommand); + echo "
\n\n"; + } + if ($module == $targetRef && $_POST["Link"] == "LINK") { // Sanity Check Failed + echo "
\nD-Star Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Cannot link to myself - Aborting link request!"; + echo "
\n
\n"; + } + if ($_POST["Link"] == "UNLINK") { // Allow Unlink no matter what + echo "
\nD-Star Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($unlinkCommand); + echo "
\n
\n"; + } + } + +unset($_POST); +echo ''; + +else: ?> +
+ +
+ + + + + + + + + + + + + +
Radio ModuleRadio ModuleReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + + + + + Link + UnLink + + +
+
+
+ + +\n"; + echo "
\n"; + echo "PiStar-Keeper Logbook\n"; + echo "\n"; + echo " \n"; + echo " \n"; + echo " \n"; + + exec ("tail -n 5 /var/pistar-keeper/pistar-keeper.log", $lines); + $counter = 0; + foreach ($lines as $line) { + echo "\n"; + $counter++; + } + + echo "
PiStar-Keeper Log Entries (UTC)PiStar-Keeper Log Entries (UTC)
".$lines[$counter]."
\n"; + echo "
\n"; + } +} +?> diff --git a/admin/dstarrepeater/local_tx.php b/admin/dstarrepeater/local_tx.php new file mode 100644 index 0000000..ba26a87 --- /dev/null +++ b/admin/dstarrepeater/local_tx.php @@ -0,0 +1,89 @@ + 0) + $configs[$key] = $value; + } + +} +$progname = basename($_SERVER['SCRIPT_FILENAME'],".php"); +$rev="20141101"; +$MYCALL=strtoupper($callsign); + +// Check if the config file exists +if (file_exists('/etc/pistar-css.ini')) { + // Use the values from the file + $piStarCssFile = '/etc/pistar-css.ini'; + if (fopen($piStarCssFile,'r')) { $piStarCss = parse_ini_file($piStarCssFile, true); } + + // Set the Values from the config file + if (isset($piStarCss['Lookup']['Service'])) { $callsignLookupSvc = $piStarCss['Lookup']['Service']; } // Lookup Service "QRZ" or "RadioID" + else { $callsignLookupSvc = "RadioID"; } // Set the default if its missing // Set the default if its missing +} else { + // Default values + $callsignLookupSvc = "RadioID"; +} + +// Safety net +if (($callsignLookupSvc != "RadioID") && ($callsignLookupSvc != "QRZ")) { $callsignLookupSvc = "RadioID"; } + +// Setup the URL(s) +if ($callsignLookupSvc == "RadioID") { $callsignLookupUrl = "https://database.radioid.net/database/view?callsign="; } +if ($callsignLookupSvc == "QRZ") { $callsignLookupUrl = "https://www.qrz.com/db/"; } + +?> + + + + + + + + + +/tmp/worked.log) 2>&1 &'); + $ci = 0; + if ($WorkedLog = fopen("/tmp/worked.log",'r')) { + while ($linkLine = fgets($WorkedLog)) { + if(preg_match_all('/^(.{19}).*My: (.*).*Your: (.*).*Rpt1: (.*).*Rpt2: (.*).*Flags: (.*)$/',$linkLine,$linx) > 0){ + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + $QSODate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); + $MyCall = str_replace(' ', '', substr($linx[2][0],0,8)); + $MyCallLink = strtok(substr($linx[2][0],0,8), " "); + $MyId = str_replace(' ', '', substr($linx[2][0],9,4)); + $YourCall = str_replace(' ', ' ', substr($linx[3][0],0,8)); + $Rpt1 = str_replace(' ', ' ', substr($linx[4][0],0,8)); + $Rpt2 = str_replace(' ', ' ', substr($linx[5][0],0,8)); + $utc_time = $QSODate; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + print ""; + print ""; } + else { print "
(dPRS)
"; } + print ""; + print ""; + print ""; + print "\n"; + } + } + fclose($WorkedLog); + } +?> +
()RPT 1RPT 2
$local_time
$MyCall"; + if($MyId) { print "/".$MyId."
$YourCall$Rpt1$Rpt2
diff --git a/admin/dstarrepeater/system.php b/admin/dstarrepeater/system.php new file mode 100644 index 0000000..036bb10 --- /dev/null +++ b/admin/dstarrepeater/system.php @@ -0,0 +1,56 @@ + 0) + $configs[$key] = $value; + } + +} +$progname = basename($_SERVER['SCRIPT_FILENAME'],".php"); +$rev="20141101"; +$MYCALL=strtoupper($callsign); +?> + 1000) { $cpuTempC = round($cpuTempCRaw / 1000, 1); } else { $cpuTempC = round($cpuTempCRaw, 1); } +$cpuTempF = round(+$cpuTempC * 9 / 5 + 32, 1); +if ($cpuTempC < 50) { $cpuTempHTML = "".$cpuTempC."°C / ".$cpuTempF."°F\n"; } +if ($cpuTempC >= 50) { $cpuTempHTML = "".$cpuTempC."°C / ".$cpuTempF."°F\n"; } +if ($cpuTempC >= 69) { $cpuTempHTML = "".$cpuTempC."°C / ".$cpuTempF."°F\n"; } +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + +

System IP Address:
', exec('hostname -I'));?>
ReleaseUptime:
', exec('uptime -p'));?>
CPU LoadCPU Temp
= 16) { echo substr(php_uname('n'), 0, 14) . '..'; } else { echo php_uname('n'); } ?> / /
">MMDVMHost">DStarRepeater">ircDDBGateway">TimeServer">PiStar-Watchdog">PiStar-Remote
+
diff --git a/admin/expert/edit_dapnetgateway.php b/admin/expert/edit_dapnetgateway.php index 40efbd4..2f6aa32 100644 --- a/admin/expert/edit_dapnetgateway.php +++ b/admin/expert/edit_dapnetgateway.php @@ -1,38 +1,4 @@ .tmp + chown www-data - * + chmod 600 (so PHP can edit the temp). - * 2. fopen('w') and fwrite the rebuilt INI text into the temp. - * 3. sudo mount -o remount,rw / + sudo install -m 644 -o root -g - * root temp -> /etc/dapnetgateway + sudo mount -o remount,ro / to - * seal the rootfs again. (See edit_mmdvmhost.php for the full - * rationale on the install vs cp+chmod+chown migration.) - * 4. sudo systemctl restart dapnetgateway.service to pick up the change. - * - * Admin-only access; the dashboard's Apache basic-auth gate is the - * sole protection. The validation is what's in the form (none, in - * effect — operator-typed values are written raw). Treat with care. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); //Load the Pi-Star Release file @@ -51,123 +17,97 @@ require_once('../config/version.php'); - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
-// doesn't persist between requests. @-suppression handles -// the case where a sudo mv (e.g. fulledit_bmapikey) already -// consumed the staging file before script end. -register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); +exec('sudo cp /etc/dapnetgateway /tmp/oXyEVXYSisDX.tmp'); +exec('sudo chown www-data:www-data /tmp/oXyEVXYSisDX.tmp'); +exec('sudo chmod 664 /tmp/oXyEVXYSisDX.tmp'); + +// ini file to open +$filepath = '/tmp/oXyEVXYSisDX.tmp'; // after the form submit if($_POST) { - $data = $_POST; - //update ini file, call function - update_ini_file($data, $filepath); + $data = $_POST; + //update ini file, call function + update_ini_file($data, $filepath); } // this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + function update_ini_file($data, $filepath) { + $content = ""; - // parse the ini file to get the sections - // parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + // parse the ini file to get the sections + // parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - $content .= $key."=".$value."\n"; - } - $content .= "\n"; - } + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + $content .= $key."=".$value."\n"; + } + $content .= "\n"; + } - // write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + // write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // L-5: atomic install replaces the prior cp + chmod + chown - // triplet (rejected by the tightened sudoers — see - // edit_mmdvmhost.php for the full rationale). - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($filepath) . ' /etc/dapnetgateway'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/oXyEVXYSisDX.tmp /etc/dapnetgateway'); // Move the file back + exec('sudo chmod 644 /etc/dapnetgateway'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/dapnetgateway'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - // Reload the affected daemon - exec('sudo systemctl restart dapnetgateway.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart dapnetgateway.service'); // Reload the daemon + return $success; + } // parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/edit_dashboard.php b/admin/expert/edit_dashboard.php index 6153da3..4bd015d 100644 --- a/admin/expert/edit_dashboard.php +++ b/admin/expert/edit_dashboard.php @@ -1,32 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "
Factory Reset NOT performed
Server-side confirmation did not match. Factory reset cancelled.
\n"; - unset($_POST); - } else { - echo "
\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "
Factory Reset Config
Loading fresh configuration file(s)...
\n"; - unset($_POST); - //Reset the config - exec('sudo mount -o remount,rw /'); // Make rootfs writable - exec('sudo rm -rf /etc/pistar-css.ini'); // Delete the Config - exec('sudo mount -o remount,ro /'); // Make rootfs read-only - echo ''; - die(); - } - } else { - //update ini file, call function - update_ini_file($data, $filepath); - } + $data = $_POST; + // Factory Reset Handler Here + if (empty($_POST['factoryReset']) != TRUE ) { + echo "
\n"; + echo "
\n"; + echo "

Factory Reset Config

\n"; + echo "
Loading fresh configuration file(s)...
\n"; + echo "
\n"; + unset($_POST); + //Reset the config + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo rm -rf /etc/pistar-css.ini'); // Delete the Config + exec('sudo mount -o remount,ro /'); // Make rootfs read-only + echo ''; + die(); + } else { + //update ini file, call function + update_ini_file($data, $filepath); + } } - //this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + //this is the function going to update your ini file + function update_ini_file($data, $filepath) { + $content = ""; - //parse the ini file to get the sections - //parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + //parse the ini file to get the sections + //parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $section = str_replace("BannerH2", "BannerH1", $section); - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - if ($value == '') { - $content .= $key."=none\n"; - } - else { - $content .= $key."=".$value."\n"; - } - } - $content .= "\n"; - } + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $section = str_replace("BannerH2", "BannerH1", $section); + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + if ($value == '') { + $content .= $key."=none\n"; + } + else { + $content .= $key."=".$value."\n"; + } + } + $content .= "\n"; + } - //write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + //write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // Atomic install — see the matching block earlier in this - // file for the rationale. Single sudo call, content + mode - // + owner all set together; no transient state on disk. - // $filepath here is the function parameter, which is the - // same per-request tempnam path created at file-top (A3-3). - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($filepath) . ' /etc/pistar-css.ini'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/bW1kd4jg6b3N0DQo.tmp /etc/pistar-css.ini'); // Move the file back + exec('sudo chmod 644 /etc/pistar-css.ini'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/pistar-css.ini'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - return $success; - } + return $success; + } //parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); @@ -212,70 +143,47 @@ if (isset($parsed_ini['Lookup']['popupWidth'])) { unset($parsed_ini['Lookup'][' if (isset($parsed_ini['Lookup']['popupHeight'])) { unset($parsed_ini['Lookup']['popupHeight']); } echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // Same hardening as edit_mmdvmhost.php (#23): escape every - // INI section / key / value before HTML interpolation. The - // save handler writes POST bytes verbatim so legitimate - // values (including any with `"` or `<`) round-trip - // byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - // keep the section as hidden text so we can update once the form submitted - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - if ( $section == "Lookup" && $key == "Service" ) { - echo "\n"; - } else { - echo "\n"; - } - } - echo "
$sectionHtml
$keyHtml\n"; - echo " \n"; - echo "
$keyHtml
\n"; - echo ''."\n"; - echo "

\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + if ( $section == "Lookup" && $key == "Service" ) { + echo "
$key
\n"; + echo " \n"; + echo "
\n"; + } else { + echo "
$key
\n"; + } + } + echo "
\n"; + echo '
'."\n"; + } echo "
"; echo "
\n"; echo 'if you took it all too far and now it makes you feel sick, click below to reset the changes made on this page, this will ONLY reset the CSS settings above and will not change any other settings or configuration.'."\n"; echo '
'."\n"; -echo csrf_field_html()."\n"; echo '
'."\n"; -// Server-side confirmation. JS factoryReset() prompts for the -// magic word and only populates this input on a match. The -// handler requires factoryResetConfirm === 'RESET' before doing -// the wipe — closes the "valid CSRF token + accidental replay" -// attack class. -echo '
'."\n"; echo '
'."\n"; echo ''."\n"; ?>
-
- diff --git a/admin/expert/edit_dmrgateway.php b/admin/expert/edit_dmrgateway.php index 973ad7a..15faad5 100644 --- a/admin/expert/edit_dmrgateway.php +++ b/admin/expert/edit_dmrgateway.php @@ -1,38 +1,4 @@ .tmp + chown www-data - * + chmod 600 (so PHP can edit the temp). - * 2. fopen('w') and fwrite the rebuilt INI text into the temp. - * 3. sudo mount -o remount,rw / + sudo install -m 644 -o root -g - * root temp -> /etc/dmrgateway + sudo mount -o remount,ro / to - * seal the rootfs again. (See edit_mmdvmhost.php for the full - * rationale on the install vs cp+chmod+chown migration.) - * 4. sudo systemctl restart dmrgateway.service to pick up the change. - * - * Admin-only access; the dashboard's Apache basic-auth gate is the - * sole protection. The validation is what's in the form (none, in - * effect — operator-typed values are written raw). Treat with care. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); //Load the Pi-Star Release file @@ -51,131 +17,105 @@ require_once('../config/version.php'); - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
-// doesn't persist between requests. @-suppression handles -// the case where a sudo mv (e.g. fulledit_bmapikey) already -// consumed the staging file before script end. -register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); +exec('sudo cp /etc/dmrgateway /tmp/fmehg65694eg.tmp'); +exec('sudo chown www-data:www-data /tmp/fmehg65694eg.tmp'); +exec('sudo chmod 664 /tmp/fmehg65694eg.tmp'); + +//ini file to open +$filepath = '/tmp/fmehg65694eg.tmp'; //after the form submit if($_POST) { - $data = $_POST; - //update ini file, call function - update_ini_file($data, $filepath); + $data = $_POST; + //update ini file, call function + update_ini_file($data, $filepath); } //this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + function update_ini_file($data, $filepath) { + $content = ""; - //parse the ini file to get the sections - //parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + //parse the ini file to get the sections + //parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - if (($section == "DMR Network 1" || $section == "DMR Network 2") && $key == "Password" && $value) { - $value = str_replace('"', "", $value); - $content .= $key."=\"".$value."\"\n"; - } elseif (($section == "DMR Network 1" || $section == "DMR Network 2") && $key == "Options" && $value) { - $value = str_replace('"', "", $value); - $content .= $key."=\"".$value."\"\n"; - } else { - $content .= $key."=".$value."\n"; - } - } - $content .= "\n"; - } + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + if (($section == "DMR Network 1" || $section == "DMR Network 2") && $key == "Password" && $value) { + $value = str_replace('"', "", $value); + $content .= $key."=\"".$value."\"\n"; + } elseif (($section == "DMR Network 1" || $section == "DMR Network 2") && $key == "Options" && $value) { + $value = str_replace('"', "", $value); + $content .= $key."=\"".$value."\"\n"; + } else { + $content .= $key."=".$value."\n"; + } + } + $content .= "\n"; + } - //write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + //write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // L-5: atomic install replaces the prior cp + chmod + chown - // triplet (rejected by the tightened sudoers — see - // edit_mmdvmhost.php for the full rationale). - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($filepath) . ' /etc/dmrgateway'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/fmehg65694eg.tmp /etc/dmrgateway'); // Move the file back + exec('sudo chmod 644 /etc/dmrgateway'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/dmrgateway'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - // Reload the affected daemon - exec('sudo systemctl restart dmrgateway.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart dmrgateway.service'); // Reload the daemon + return $success; + } //parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/edit_dstarrepeater.php b/admin/expert/edit_dstarrepeater.php index be76944..b8bdfb0 100644 --- a/admin/expert/edit_dstarrepeater.php +++ b/admin/expert/edit_dstarrepeater.php @@ -1,29 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; //append the values foreach($values as $key=>$value) { - if ($value == '') { - $content .= $key."= \n"; + if ($value == '') { + $content .= $key."= \n"; } else { $content .= $key."=".$value."\n"; } } - } + } - // write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + // write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // /etc/dstarrepeater is a FLAT key=value file on disk — the - // synthetic [dstarrepeater] header is injected only for - // parse_ini_file()'s benefit. Strip it via PHP and install - // the cleaned content directly (L-7: drops sudo sed -i; - // L-5: collapses cp + chmod + chown into one atomic install). - // See edit_ircddbgateway.php for the full rationale. - $etcContent = preg_replace('/^\[dstarrepeater\]\r?\n/m', '', $content); - // A3-3: per-request random staging — see edit_ircddbgateway.php - $etcStaging = tempnam('/tmp', 'pistar-edit-etc-'); - file_put_contents($etcStaging, $etcContent); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/ZHN0YXJyZXBlYXRlcg.tmp /etc/dstarrepeater'); // Move the file back + exec('sudo sed -i \'/\\[dstarrepeater\\]/d\' /etc/dstarrepeater'); // Clean up file mangling + exec('sudo chmod 644 /etc/dstarrepeater'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/dstarrepeater'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($etcStaging) . ' /etc/dstarrepeater'); - exec('sudo mount -o remount,ro /'); - @unlink($etcStaging); - - // Reload the affected daemon - exec('sudo systemctl restart dstarrepeater.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart dstarrepeater.service'); // Reload the daemon + return $success; + } // parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/edit_ircddbgateway.php b/admin/expert/edit_ircddbgateway.php index 7f58b0d..46a5ad2 100644 --- a/admin/expert/edit_ircddbgateway.php +++ b/admin/expert/edit_ircddbgateway.php @@ -1,28 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
$values) { + foreach($data as $section=>$values) { // UnBreak special cases $section = str_replace("_", " ", $section); $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - if ($value == '') { - $content .= $key."= \n"; - } - else { - $content .= $key."=".$value."\n"; - } - } - } + //append the values + foreach($values as $key=>$value) { + if ($value == '') { + $content .= $key."= \n"; + } + else { + $content .= $key."=".$value."\n"; + } + } + } - // write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + // write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // /etc/ircddbgateway is a FLAT key=value file on disk — the - // synthetic [ircddbgateway] header was injected at line ~75 - // only to satisfy parse_ini_file()'s section model. The /tmp - // staging file keeps the header (so the form re-render via - // parse_ini_file at the bottom of this script still finds - // sections); the on-disk version must not. Strip via PHP's - // preg_replace and install the cleaned content directly — - // drops the prior `sudo sed -i` from this code path (L-7). - $etcContent = preg_replace('/^\[ircddbgateway\]\r?\n/m', '', $content); - // A3-3: per-request random staging file rather than a - // predictable hardcoded /tmp/.tmp path. tempnam() also - // creates the file mode 600 — and since this is a freshly - // created file (not yet referenced anywhere), there's no - // race for an attacker to swap in a symlink before our write. - $etcStaging = tempnam('/tmp', 'pistar-edit-etc-'); - file_put_contents($etcStaging, $etcContent); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/aXJjZGRiZ2F0ZXdheQ.tmp /etc/ircddbgateway'); // Move the file back + exec('sudo sed -i \'/\\[ircddbgateway\\]/d\' /etc/ircddbgateway'); // Clean up file mangling + exec('sudo chmod 644 /etc/ircddbgateway'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/ircddbgateway'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - // Atomic install: content + mode + owner set in one syscall - // sequence (B5 / L-5 pattern). Replaces the prior cp + - // chmod + chown trio so an interrupted RW window can't leave - // /etc/ircddbgateway in a transient state. - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($etcStaging) . ' /etc/ircddbgateway'); - exec('sudo mount -o remount,ro /'); - @unlink($etcStaging); - - // Reload the affected daemon - exec('sudo systemctl restart ircddbgateway.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart ircddbgateway.service'); // Reload the daemon + return $success; + } // parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/edit_mmdvmhost.php b/admin/expert/edit_mmdvmhost.php index 3355164..3432452 100644 --- a/admin/expert/edit_mmdvmhost.php +++ b/admin/expert/edit_mmdvmhost.php @@ -1,42 +1,4 @@ .tmp + chown www-data - * + chmod 600 (so PHP can edit the temp). - * 2. fopen('w') and fwrite the rebuilt INI text into the temp. - * 3. sudo mount -o remount,rw / + sudo install -m 644 -o root -g - * root temp -> /etc/mmdvmhost + sudo mount -o remount,ro / to - * seal the rootfs again. (L-5: collapses the prior cp + chmod + - * chown triplet into one atomic call — same idiom used by - * configure.php's gateway-save block. The triplet would also - * be rejected by the tightened /etc/sudoers.d/pistar-dashboard - * because it allowlists install but not bare cp+chmod+chown - * against /etc/.) - * 4. sudo systemctl restart mmdvmhost.service to pick up the change. - * - * Admin-only access; the dashboard's Apache basic-auth gate is the - * sole protection. The validation is what's in the form (none, in - * effect — operator-typed values are written raw). Treat with care. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); //Load the Pi-Star Release file @@ -55,162 +17,121 @@ require_once('../config/version.php'); - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
-// doesn't persist between requests. @-suppression handles -// the case where a sudo mv (e.g. fulledit_bmapikey) already -// consumed the staging file before script end. -register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); +exec('sudo cp /etc/mmdvmhost /tmp/bW1kdm1ob3N0DQo.tmp'); +exec('sudo chown www-data:www-data /tmp/bW1kdm1ob3N0DQo.tmp'); +exec('sudo chmod 664 /tmp/bW1kdm1ob3N0DQo.tmp'); + +//ini file to open +$filepath = '/tmp/bW1kdm1ob3N0DQo.tmp'; //after the form submit if($_POST) { - $data = $_POST; - //update ini file, call function - update_ini_file($data, $filepath); + $data = $_POST; + //update ini file, call function + update_ini_file($data, $filepath); } //this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + function update_ini_file($data, $filepath) { + $content = ""; - //parse the ini file to get the sections - //parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + //parse the ini file to get the sections + //parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - if ($section == "DMR Network" && $key == "Password" && $value) { - $value = str_replace('"', "", $value); - $content .= $key."=\"".$value."\"\n"; - } - elseif ($section == "DMR Network" && $key == "Options" && $value) { - $value = str_replace('"', "", $value); - $content .= $key."=\"".$value."\"\n"; - } - elseif ($section == "DMR Network" && $key == "Options" && !$value) { - $content .= $key."= \n"; - } - elseif ($value == '') { + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + if ($section == "DMR Network" && $key == "Password" && $value) { + $value = str_replace('"', "", $value); + $content .= $key."=\"".$value."\"\n"; + } + elseif ($section == "DMR Network" && $key == "Options" && $value) { + $value = str_replace('"', "", $value); + $content .= $key."=\"".$value."\"\n"; + } + elseif ($section == "DMR Network" && $key == "Options" && !$value) { + $content .= $key."= \n"; + } + elseif ($value == '') { $content .= $key."=none\n"; } - else { - $content .= $key."=".$value."\n"; - } - } - $content .= "\n"; - } + else { + $content .= $key."=".$value."\n"; + } + } + $content .= "\n"; + } - //write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + //write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // Updates complete - install the working file back to the - // proper location. L-5: atomic install replaces the prior - // cp + chmod + chown triplet (which the tightened - // /etc/sudoers.d/pistar-dashboard rejects on the bare - // chmod/chown against /etc/ — only the install pattern - // is allowlisted there). - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($filepath) . ' /etc/mmdvmhost'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/bW1kdm1ob3N0DQo.tmp /etc/mmdvmhost'); // Move the file back + exec('sudo chmod 644 /etc/mmdvmhost'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/mmdvmhost'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - // Reload the affected daemon - exec('sudo systemctl restart mmdvmhost.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart mmdvmhost.service'); // Reload the daemon + return $success; + } //parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // INI section / key / value all come from /etc/mmdvmhost. - // Operator-trusted in principle, but the M-3 audit class - // means a value with a literal `"` or `<` (legitimate INI - // content — e.g. "Options=foo=1,bar" or a callsign with a - // space) breaks out of `value="…"` attributes and renders - // as HTML. - // - // htmlspecialchars(ENT_QUOTES) preserves round-trip safety: - // on display: `"` -> `"`, `<` -> `<` etc. - // browser decode (form parse): `"` -> `"` again. - // POST: the raw byte gets back to the save handler. - // save handler at line ~108: writes `key=value` to INI - // verbatim — no further escaping or unescaping. - // So values like `Options="foo=1,bar"` go in, get displayed - // as `Options="foo=1,bar"`, the browser still shows - // `"foo=1,bar"` in the input field, and re-saving produces - // a byte-identical INI line. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - // keep the section as hidden text so we can update once the form submitted - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - if (($key == "Options") || ($value)) { - echo "\n"; - } - elseif (($key == "Display") && ($value == '')) { - echo "\n"; - } - else { - echo "\n"; - } - } - echo "
$sectionHtml
$keyHtml
$keyHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + if (($key == "Options") || ($value)) { + echo "
$key
\n"; + } + elseif (($key == "Display") && ($value == '')) { + echo "
$key
\n"; + } + else { + echo "
$key
\n"; + } + } + echo "
\n"; + echo '
'."\n"; + } echo "
"; ?>
-
- diff --git a/admin/expert/edit_nxdngateway.php b/admin/expert/edit_nxdngateway.php index 60b2a9b..e5da4dc 100644 --- a/admin/expert/edit_nxdngateway.php +++ b/admin/expert/edit_nxdngateway.php @@ -1,38 +1,4 @@ .tmp + chown www-data - * + chmod 600 (so PHP can edit the temp). - * 2. fopen('w') and fwrite the rebuilt INI text into the temp. - * 3. sudo mount -o remount,rw / + sudo install -m 644 -o root -g - * root temp -> /etc/nxdngateway + sudo mount -o remount,ro / to - * seal the rootfs again. (See edit_mmdvmhost.php for the full - * rationale on the install vs cp+chmod+chown migration.) - * 4. sudo systemctl restart nxdngateway.service to pick up the change. - * - * Admin-only access; the dashboard's Apache basic-auth gate is the - * sole protection. The validation is what's in the form (none, in - * effect — operator-typed values are written raw). Treat with care. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); //Load the Pi-Star Release file @@ -51,124 +17,98 @@ require_once('../config/version.php'); - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
-// doesn't persist between requests. @-suppression handles -// the case where a sudo mv (e.g. fulledit_bmapikey) already -// consumed the staging file before script end. -register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); +exec('sudo cp /etc/nxdngateway /tmp/aFEds45dgs4tFS.tmp'); +exec('sudo chown www-data:www-data /tmp/aFEds45dgs4tFS.tmp'); +exec('sudo chmod 664 /tmp/aFEds45dgs4tFS.tmp'); + +// ini file to open +$filepath = '/tmp/aFEds45dgs4tFS.tmp'; // after the form submit if($_POST) { - $data = $_POST; - //update ini file, call function - update_ini_file($data, $filepath); + $data = $_POST; + //update ini file, call function + update_ini_file($data, $filepath); } // this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + function update_ini_file($data, $filepath) { + $content = ""; - // parse the ini file to get the sections - // parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + // parse the ini file to get the sections + // parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - if (strpos($section, 'aprs') !== false) { $section = str_replace("_", ".", $section); } - else { $section = str_replace("_", " ", $section); $section = str_replace(".", " ", $section); } - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - $content .= $key."=".$value."\n"; - } - $content .= "\n"; - } + foreach($data as $section=>$values) { + // UnBreak special cases + if (strpos($section, 'aprs') !== false) { $section = str_replace("_", ".", $section); } + else { $section = str_replace("_", " ", $section); $section = str_replace(".", " ", $section); } + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + $content .= $key."=".$value."\n"; + } + $content .= "\n"; + } - // write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + // write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // L-5: atomic install replaces the prior cp + chmod + chown - // triplet (rejected by the tightened sudoers — see - // edit_mmdvmhost.php for the full rationale). - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($filepath) . ' /etc/nxdngateway'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/aFEds45dgs4tFS.tmp /etc/nxdngateway'); // Move the file back + exec('sudo chmod 644 /etc/nxdngateway'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/nxdngateway'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - // Reload the affected daemon - exec('sudo systemctl restart nxdngateway.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart nxdngateway.service'); // Reload the daemon + return $success; + } // parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/edit_p25gateway.php b/admin/expert/edit_p25gateway.php index cb25861..316ea1d 100644 --- a/admin/expert/edit_p25gateway.php +++ b/admin/expert/edit_p25gateway.php @@ -1,38 +1,4 @@ .tmp + chown www-data - * + chmod 600 (so PHP can edit the temp). - * 2. fopen('w') and fwrite the rebuilt INI text into the temp. - * 3. sudo mount -o remount,rw / + sudo install -m 644 -o root -g - * root temp -> /etc/p25gateway + sudo mount -o remount,ro / to - * seal the rootfs again. (See edit_mmdvmhost.php for the full - * rationale on the install vs cp+chmod+chown migration.) - * 4. sudo systemctl restart p25gateway.service to pick up the change. - * - * Admin-only access; the dashboard's Apache basic-auth gate is the - * sole protection. The validation is what's in the form (none, in - * effect — operator-typed values are written raw). Treat with care. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); //Load the Pi-Star Release file @@ -51,123 +17,97 @@ require_once('../config/version.php'); - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
-// doesn't persist between requests. @-suppression handles -// the case where a sudo mv (e.g. fulledit_bmapikey) already -// consumed the staging file before script end. -register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); +exec('sudo cp /etc/p25gateway /tmp/aFE45dgs4tFS.tmp'); +exec('sudo chown www-data:www-data /tmp/aFE45dgs4tFS.tmp'); +exec('sudo chmod 664 /tmp/aFE45dgs4tFS.tmp'); + +// ini file to open +$filepath = '/tmp/aFE45dgs4tFS.tmp'; // after the form submit if($_POST) { - $data = $_POST; - //update ini file, call function - update_ini_file($data, $filepath); + $data = $_POST; + //update ini file, call function + update_ini_file($data, $filepath); } // this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + function update_ini_file($data, $filepath) { + $content = ""; - // parse the ini file to get the sections - // parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + // parse the ini file to get the sections + // parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - $content .= $key."=".$value."\n"; - } - $content .= "\n"; - } + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + $content .= $key."=".$value."\n"; + } + $content .= "\n"; + } - // write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + // write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // L-5: atomic install replaces the prior cp + chmod + chown - // triplet (rejected by the tightened sudoers — see - // edit_mmdvmhost.php for the full rationale). - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($filepath) . ' /etc/p25gateway'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/aFE45dgs4tFS.tmp /etc/p25gateway'); // Move the file back + exec('sudo chmod 644 /etc/p25gateway'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/p25gateway'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - // Reload the affected daemon - exec('sudo systemctl restart p25gateway.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart p25gateway.service'); // Reload the daemon + return $success; + } // parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/edit_starnetserver.php b/admin/expert/edit_starnetserver.php index bd2d95b..c6195e3 100644 --- a/admin/expert/edit_starnetserver.php +++ b/admin/expert/edit_starnetserver.php @@ -1,26 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; //append the values foreach($values as $key=>$value) { - if ($value == '') { - $content .= $key."=".$value." \n"; + if ($value == '') { + $content .= $key."=".$value." \n"; } else { $content .= $key."=".$value."\n"; } } - } + } - // write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + // write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // /etc/starnetserver is a FLAT key=value file on disk — the - // synthetic [starnetserver] header is injected only for - // parse_ini_file()'s benefit. Strip it via PHP and install - // the cleaned content directly (L-7: drops sudo sed -i; - // L-5: collapses cp + chmod + chown into one atomic install). - // See edit_ircddbgateway.php for the full rationale. - $etcContent = preg_replace('/^\[starnetserver\]\r?\n/m', '', $content); - // A3-3: per-request random staging — see edit_ircddbgateway.php - $etcStaging = tempnam('/tmp', 'pistar-edit-etc-'); - file_put_contents($etcStaging, $etcContent); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/c3Rhcm5ldHNlcnZlcg.tmp /etc/starnetserver'); // Move the file back + exec('sudo sed -i \'/\\[starnetserver\\]/d\' /etc/starnetserver'); // Clean up file mangling + exec('sudo chmod 644 /etc/starnetserver'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/starnetserver'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($etcStaging) . ' /etc/starnetserver'); - exec('sudo mount -o remount,ro /'); - @unlink($etcStaging); - - // Reload the affected daemon so the saved edits take effect - // without a manual restart. Was commented out historically; - // restored so behaviour matches the other edit_*.php files. - exec('sudo systemctl restart starnetserver.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + //exec('sudo systemctl restart starnetserver.service'); // Reload the daemon + return $success; + } // parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/edit_timeserver.php b/admin/expert/edit_timeserver.php index 2cb10fd..4ad7569 100644 --- a/admin/expert/edit_timeserver.php +++ b/admin/expert/edit_timeserver.php @@ -1,28 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; //append the values foreach($values as $key=>$value) { - if ($value == '') { - $content .= $key."= \n"; + if ($value == '') { + $content .= $key."= \n"; } else { $content .= $key."=".$value."\n"; } } - } + } - // write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + // write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // /etc/timeserver is a FLAT key=value file on disk — the - // synthetic [timeserver] header is injected only for - // parse_ini_file()'s benefit. Strip it via PHP and install - // the cleaned content directly (L-7: drops sudo sed -i; - // L-5: collapses cp + chmod + chown into one atomic install). - // See edit_ircddbgateway.php for the full rationale. - $etcContent = preg_replace('/^\[timeserver\]\r?\n/m', '', $content); - // A3-3: per-request random staging — see edit_ircddbgateway.php - $etcStaging = tempnam('/tmp', 'pistar-edit-etc-'); - file_put_contents($etcStaging, $etcContent); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/dGltZXNlcnZlcg.tmp /etc/timeserver'); // Move the file back + exec('sudo sed -i \'/\\[timeserver\\]/d\' /etc/timeserver'); // Clean up file mangling + exec('sudo chmod 644 /etc/timeserver'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/timeserver'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($etcStaging) . ' /etc/timeserver'); - exec('sudo mount -o remount,ro /'); - @unlink($etcStaging); - - // Reload the affected daemon - exec('sudo systemctl restart timeserver.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart timeserver.service'); // Reload the daemon + return $success; + } // parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/edit_ysfgateway.php b/admin/expert/edit_ysfgateway.php index 370a816..5634838 100644 --- a/admin/expert/edit_ysfgateway.php +++ b/admin/expert/edit_ysfgateway.php @@ -1,38 +1,4 @@ .tmp + chown www-data - * + chmod 600 (so PHP can edit the temp). - * 2. fopen('w') and fwrite the rebuilt INI text into the temp. - * 3. sudo mount -o remount,rw / + sudo install -m 644 -o root -g - * root temp -> /etc/ysfgateway + sudo mount -o remount,ro / to - * seal the rootfs again. (See edit_mmdvmhost.php for the full - * rationale on the install vs cp+chmod+chown migration.) - * 4. sudo systemctl restart ysfgateway.service to pick up the change. - * - * Admin-only access; the dashboard's Apache basic-auth gate is the - * sole protection. The validation is what's in the form (none, in - * effect — operator-typed values are written raw). Treat with care. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); //Load the Pi-Star Release file @@ -51,124 +17,98 @@ require_once('../config/version.php'); - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
-// doesn't persist between requests. @-suppression handles -// the case where a sudo mv (e.g. fulledit_bmapikey) already -// consumed the staging file before script end. -register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); +exec('sudo cp /etc/ysfgateway /tmp/eXNmZ2F0ZXdheQ.tmp'); +exec('sudo chown www-data:www-data /tmp/eXNmZ2F0ZXdheQ.tmp'); +exec('sudo chmod 664 /tmp/eXNmZ2F0ZXdheQ.tmp'); + +// ini file to open +$filepath = '/tmp/eXNmZ2F0ZXdheQ.tmp'; // after the form submit if($_POST) { - $data = $_POST; - //update ini file, call function - update_ini_file($data, $filepath); + $data = $_POST; + //update ini file, call function + update_ini_file($data, $filepath); } // this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + function update_ini_file($data, $filepath) { + $content = ""; - // parse the ini file to get the sections - // parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + // parse the ini file to get the sections + // parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - if (strpos($section, 'aprs') !== false) { $section = str_replace("_", ".", $section); } - else { $section = str_replace("_", " ", $section); $section = str_replace(".", " ", $section); } - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - $content .= $key."=".$value."\n"; - } - $content .= "\n"; - } + foreach($data as $section=>$values) { + // UnBreak special cases + if (strpos($section, 'aprs') !== false) { $section = str_replace("_", ".", $section); } + else { $section = str_replace("_", " ", $section); $section = str_replace(".", " ", $section); } + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + $content .= $key."=".$value."\n"; + } + $content .= "\n"; + } - // write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + // write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // L-5: atomic install replaces the prior cp + chmod + chown - // triplet (rejected by the tightened sudoers — see - // edit_mmdvmhost.php for the full rationale). - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 644 -o root -g root ' - . escapeshellarg($filepath) . ' /etc/ysfgateway'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/eXNmZ2F0ZXdheQ.tmp /etc/ysfgateway'); // Move the file back + exec('sudo chmod 644 /etc/ysfgateway'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/ysfgateway'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - // Reload the affected daemon - exec('sudo systemctl restart ysfgateway.service'); // Reload the daemon - return $success; - } + // Reload the affected daemon + exec('sudo systemctl restart ysfgateway.service'); // Reload the daemon + return $success; + } // parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // keep the section as hidden text so we can update once the form submitted - // INI section / key / value all come from the underlying - // /etc/ file. Same hardening as edit_mmdvmhost.php - // (#23): htmlspecialchars(ENT_QUOTES) on display so a value - // with a literal `"` or `<` (e.g. an Options string) can't - // break out of the `value="…"` attribute. The save handler - // writes the POST bytes verbatim, so legitimate quoted - // values round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - echo "\n"; - } - echo "
$sectionHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + echo "
$key
\n"; + } + echo "
\n"; + echo '
'."\n"; + } echo ""; ?>
-
- diff --git a/admin/expert/fulledit_bmapikey.php b/admin/expert/fulledit_bmapikey.php index a9c55aa..4c67e91 100644 --- a/admin/expert/fulledit_bmapikey.php +++ b/admin/expert/fulledit_bmapikey.php @@ -1,28 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
/tmp/d39fk36sg55433gd.tmp'); + exec('sudo echo "apikey=None" >> /tmp/d39fk36sg55433gd.tmp'); } -exec('sudo chown www-data:www-data ' . escapeshellarg($filepath)); -exec('sudo chmod 600 ' . escapeshellarg($filepath)); +exec('sudo chown www-data:www-data /tmp/d39fk36sg55433gd.tmp'); +exec('sudo chmod 664 /tmp/d39fk36sg55433gd.tmp'); + +//ini file to open +$filepath = '/tmp/d39fk36sg55433gd.tmp'; //after the form submit if($_POST) { - $data = $_POST; - //update ini file, call function - update_ini_file($data, $filepath); + $data = $_POST; + //update ini file, call function + update_ini_file($data, $filepath); } //this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + function update_ini_file($data, $filepath) { + $content = ""; - //parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + //parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - // Strip CR/LF from values before they reach the INI - // line. Same rationale as fulledit_dapnetapi.php: a - // newline inside $value would split into a fresh - // INI line and let an attacker inject extra keys. - $value = str_replace(array("\r", "\n"), "", (string)$value); - if ($value == '') { + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + if ($value == '') { $content .= $key."=none\n"; } else { - $content .= $key."=".$value."\n"; - } - } - $content .= "\n"; - } + $content .= $key."=".$value."\n"; + } + } + $content .= "\n"; + } - //write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + //write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // Atomic install: mode + owner set in one syscall sequence. - // /etc/bmapi.key holds the BrandMeister API token — mode 600 - // keeps it readable only by www-data (the dashboard user). - // Owner left as www-data because banner_warnings.inc / bm_links.php / - // bm_manager.php read the file directly via parse_ini_file() - // without sudo — switching to root:root here would silently - // break those reads. (Tightening to root:root is a follow-up - // once the read sites move to a sudo-cat helper.) - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 600 -o www-data -g www-data ' - . escapeshellarg($filepath) . ' /etc/bmapi.key'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo mv /tmp/d39fk36sg55433gd.tmp /etc/bmapi.key'); // Move the file back + exec('sudo chmod 644 /etc/bmapi.key'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/bmapi.key'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - return $success; - } + return $success; + } //parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); if (!isset($parsed_ini['key']['apikey'])) { $parsed_ini['key']['apikey'] = ""; } echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // INI section / key / value all come from /etc/bmapi.key. Same - // hardening as edit_mmdvmhost.php (#23) but the value lands - // inside a body — htmlspecialchars - // covers both attribute and body contexts safely. Browser - // decodes the named entities on form submit, so legitimate - // values containing `<`, `>`, `&`, `"` round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - // keep the section as hidden text so we can update once the form submitted - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - if (($key == "Options") || ($value)) { - echo "\n"; - } - elseif (($key == "Display") && ($value == '')) { - echo "\n"; - } - else { - echo "\n"; - } - } - echo "
$sectionHtml
$keyHtml
$keyHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + if (($key == "Options") || ($value)) { + echo "
$key
\n"; + } + elseif (($key == "Display") && ($value == '')) { + echo "
$key
\n"; + } + else { + echo "
$key
\n"; + } + } + echo "
\n"; + echo ''."\n"; + echo "
\n"; + } echo "
"; ?>
-
- diff --git a/admin/expert/fulledit_cron.php b/admin/expert/fulledit_cron.php index 91d3e67..fe76fee 100644 --- a/admin/expert/fulledit_cron.php +++ b/admin/expert/fulledit_cron.php @@ -1,30 +1,4 @@ .tmp, then sudo-copied back into /etc/crontab. - * No daemon restart (cron rereads its config automatically). - * - * Operator can edit any cron line, including the pistar-* timer hooks - * — read carefully before saving. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); //Load the Pi-Star Release file @@ -43,334 +17,66 @@ require_once('../config/version.php'); - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
- */ -function pistar_cron_validate($content) -{ - $rules = array( - // Password modification commands. The leading character class - // matches start-of-line OR a typical token boundary (whitespace, - // path separator, shell metas, or `=` so we catch X=passwd). - // \b at the end stops "passwords" / "chpasswdtest" matching. - '#(?:^|[\s/;|&`$()=])(passwd|chpasswd|htpasswd)\b#i' - => 'invokes a password-modification command (passwd / chpasswd / htpasswd)', - // usermod -p sets a password hash directly, no PAM, no audit. - '#\busermod\b[^\n]*\s-p\b#i' - => 'usermod -p sets a password hash directly', - // Reference to any auth file. Even reading these from cron is - // unusual; writing is highly suspicious. Catches /etc/shadow, - // /etc/passwd, /etc/passwd-, and any .htpasswd path including - // /var/www/.htpasswd. - '#(/etc/shadow|/etc/passwd|\.htpasswd)\b#i' - => 'references an authentication file path', - // Netcat — block any invocation. Operators with a legitimate - // use should script it outside cron. Blocking outright is - // simpler than disambiguating safe vs. unsafe nc flags. - '#(?:^|[\s/;|&`$()=])(nc|ncat|netcat)\b#i' - => 'invokes nc / ncat / netcat', - // socat with EXEC: or SYSTEM: targets — process-spawning. - '#\bsocat\b[^\n]*\b(EXEC|SYSTEM):#i' - => 'socat with EXEC/SYSTEM token (spawns a process)', - // Bash builtin /dev/tcp / /dev/udp redirect — classic reverse- - // shell idiom (`bash -i >& /dev/tcp/h/p 0>&1`). No legitimate - // cron use. - '#/dev/(?:tcp|udp)/#' - => 'reads or writes /dev/tcp/* or /dev/udp/* (reverse-shell pattern)', - // Download-pipe-shell. Catches `curl ... | sh`, `wget ... | bash`, - // etc. The `[^|\n]*` between the fetch tool and the pipe stops - // a stray pipe later in a long line giving false positives. - '#\b(curl|wget|fetch)\b[^|\n]*\|\s*(?:bash|sh|zsh|ksh|dash|exec)\b#i' - => 'pipes downloaded content directly into a shell', - // python reverse-shell one-liners — heuristic on imports/calls - // commonly used in the published payloads. - '#\bpython[23]?\b[^\n]*-c[^\n]*(?:socket\.socket|os\.dup2)#i' - => 'python reverse-shell pattern', - // perl reverse-shell one-liner — `perl -e \'use Socket; ...\'` - '#\bperl\b[^\n]*-e[^\n]*\bSocket\b#i' - => 'perl reverse-shell pattern', - - // ====== Obfuscation / decoder patterns ====== - // No legitimate cron use for inline encoded payloads. Operators - // who need to encode/decode something should do it in a script, - // not in a cron line. Catches the common payload-wrapper idioms. - - // base64 in any form — the command, the python module, perl's - // decode_base64, etc. Substring match (no \b) so it also - // catches "decode_base64", "MIME::Base64", "base64.b64decode". - '#base64#i' - => 'references base64 (no legitimate cron use; payload-obfuscation idiom)', - // python's base64 module exposes b64decode / b64encode aliases - // that don't contain the literal "base64" substring. - '#\bb64(?:decode|encode)\b#i' - => 'python b64decode/b64encode (payload decoder)', - // python's bytes.fromhex(...) — turns a hex string into bytes - // for runtime execution. - '#\bfromhex\b#i' - => 'fromhex (hex payload decoder)', - // xxd dumps / reverses hex. Reverse mode (-r) is a payload - // decoder; forward mode is hex-dumping which has no cron use. - // Block the binary outright. - '#\bxxd\b#i' - => 'invokes xxd (hex dump / reverse-mode payload decoder)', - // Shell hex / unicode escape literals. `printf \'\x70\x61\x73\x73\'` - // spells "pass" at runtime — pure obfuscation in cron context. - '#\\\\x[0-9a-fA-F]{2}#' - => 'shell hex-escape literal (\\xNN — payload obfuscation)', - '#\\\\u[0-9a-fA-F]{4}#' - => 'shell unicode-escape literal (\\uNNNN — payload obfuscation)', - // eval interprets its argument as shell — opaque to anyone - // reading the cron line. - '#(?:^|[\s/;|&`$()=])eval\b#i' - => 'invokes eval (opaque shell-string execution)', - // openssl -d in any context (enc -d, base64 -d, ...) is a - // generic decoder. - '#\bopenssl\b[^\n]*\s-d\b#i' - => 'openssl with -d (decoder)', - ); - - $blockers = array(); - $lines = explode("\n", $content); - foreach ($lines as $i => $line) { - $trimmed = ltrim($line); - if ($trimmed === '' || $trimmed[0] === '#') { - continue; - } - foreach ($rules as $pattern => $reason) { - if (preg_match($pattern, $line)) { - $blockers[] = sprintf( - 'line %d (%s): %s', - $i + 1, - $reason, - substr(trim($line), 0, 100) - ); - break; // one diagnostic per line is enough - } - } - } - return $blockers; -} - -$cronBlockers = array(); -$saveError = false; -$saveOk = false; -$readError = false; if(isset($_POST['data'])) { - // Normalise CRLF → LF before validation so a Windows browser's - // submission scans byte-identical to the on-disk form. - $rawData = str_replace("\r", "", (string)$_POST['data']); - $cronBlockers = pistar_cron_validate($rawData); + // File Wrangling + exec('sudo cp /etc/crontab /tmp/a8h4d8n3c83h4.tmp'); + exec('sudo chown www-data:www-data /tmp/a8h4d8n3c83h4.tmp'); + exec('sudo chmod 664 /tmp/a8h4d8n3c83h4.tmp'); - if (!empty($cronBlockers)) { - // Validation failed — DO NOT touch /etc/crontab. Surface - // the diagnostics in the page and re-render the form - // with the operator's submitted content so they can - // fix in place without retyping. - $theData = $rawData; - error_log('Pi-Star fulledit_cron.php: rejected save with ' - . count($cronBlockers) . ' blocked line(s)'); - } else { - // A3-3 — see edit_ircddbgateway.php for the full TOCTOU - // rationale. Per-request random staging path defeats - // the predictable-name pre-create / symlink class. - $filepath = tempnam('/tmp', 'pistar-edit-'); - register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); - $fh = fopen($filepath, 'w'); - if ($fh !== false) { - fwrite($fh, $rawData); - fclose($fh); - } + // Open the file and write the data + $filepath = '/tmp/a8h4d8n3c83h4.tmp'; + $fh = fopen($filepath, 'w'); + fwrite($fh, str_replace("\r", "", $_POST['data'])); + fclose($fh); + exec('sudo mount -o remount,rw /'); + exec('sudo cp /tmp/a8h4d8n3c83h4.tmp /etc/crontab'); + exec('sudo chmod 644 /etc/crontab'); + exec('sudo chown root:root /etc/crontab'); + exec('sudo mount -o remount,ro /'); - // Write through the one sudoers-allowlisted primitive for - // this file: `sudo sed -i … /etc/crontab`. (The previous - // `install … /etc/crontab` had no matching sudoers rule and - // was silently rejected — saves looked successful but never - // touched disk.) The operator's bytes are poured over the - // file with sed's `1r ` + `d` idiom: read the staged - // temp file in on the first cycle, delete every original - // line, leaving an exact byte-for-byte copy. The operator's - // content never enters the sed script — only the temp file - // PATH does — so there is no sed/shell-injection surface. - // sed -i preserves the existing root:root 644 (verified on a - // live host), so no follow-up chown/chmod is needed. - // $sedOut is an unused placeholder (sed -i is silent on - // success); the save status we act on is the exit code $rc - // plus the read-back comparison below. - $rc = 0; - $sedOut = array(); - exec('sudo mount -o remount,rw /'); - exec('sudo sed -i -e ' . escapeshellarg('1r ' . $filepath) . ' -e d /etc/crontab', $sedOut, $rc); - exec('sudo mount -o remount,ro /'); // always re-protect the rootfs - - // Loud-failure check. The old code unconditionally rendered - // "as saved", which is exactly how the broken write hid for - // weeks. Read /etc/crontab back (world-readable) and compare - // byte-for-byte: a non-zero sed exit OR any mismatch means - // the save did not land. This also covers the degenerate - // empty-crontab corner, where `1r` never fires and the file - // would be left empty. - $onDisk = @file_get_contents('/etc/crontab'); - if ($rc !== 0 || $onDisk !== $rawData) { - $saveError = true; - error_log('Pi-Star fulledit_cron.php: crontab save FAILED (sed rc=' - . $rc . ', readback ' - . ($onDisk === $rawData ? 'matched' : 'MISMATCHED') . ')'); - } else { - $saveOk = true; - } - - // Re-render the submitted content either way so a failed - // save never discards the operator's edits. - $theData = $rawData; - } -} else { - // A3-3 — see edit_ircddbgateway.php for the full TOCTOU rationale. - $filepath = tempnam('/tmp', 'pistar-edit-'); - register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); - exec('sudo cp /etc/crontab ' . escapeshellarg($filepath)); - exec('sudo chown www-data:www-data ' . escapeshellarg($filepath)); - exec('sudo chmod 600 ' . escapeshellarg($filepath)); + // Re-open the file and read it $fh = fopen($filepath, 'r'); - if ($fh === false) { - // The privileged copy of /etc/crontab could not be staged - // (sudo cp/chown/chmod failed). Surface a read error and show - // an empty editor rather than a blank-but-editable textarea — - // saving from the latter would overwrite /etc/crontab with - // nothing. - $theData = ''; - $readError = true; - error_log('Pi-Star fulledit_cron.php: could not stage /etc/crontab for reading'); - } else { - $sz = filesize($filepath); - $theData = $sz > 0 ? fread($fh, $sz) : ''; - fclose($fh); - } + $theData = fread($fh, filesize($filepath)); + +} else { + // File Wrangling + exec('sudo cp /etc/crontab /tmp/a8h4d8n3c83h4.tmp'); + exec('sudo chown www-data:www-data /tmp/a8h4d8n3c83h4.tmp'); + exec('sudo chmod 664 /tmp/a8h4d8n3c83h4.tmp'); + + // Open the file and read it + $filepath = '/tmp/a8h4d8n3c83h4.tmp'; + $fh = fopen($filepath, 'r'); + $theData = fread($fh, filesize($filepath)); } +fclose($fh); ?> - -
-Save rejected — the cron editor blocks lines that match common privilege-escalation patterns. -
    -' . htmlspecialchars($b, ENT_QUOTES, 'UTF-8') . "\n"; -} ?> -
-

Edit the offending line(s) and re-submit, or revert your changes. -If you have a legitimate need to schedule one of these patterns, use SSH and edit -/etc/crontab directly — the dashboard editor enforces these checks -to limit the damage of stolen dashboard credentials.

-
- - -
-Save failed — /etc/crontab was not updated. -

The write was rejected or the file did not match after saving. Your edits are -preserved below — try again, or edit /etc/crontab directly over SSH.

-
- -
-Crontab saved. -
- - - -
-Could not read /etc/crontab. -

The current crontab could not be loaded, so the editor below is empty. -Do not save — doing so would overwrite /etc/crontab with nothing. Reload the page, or edit -/etc/crontab directly over SSH.

-
- +

System Cron (Full Edit)

+
- -
- +
+
+
-
- diff --git a/admin/expert/fulledit_dapnetapi.php b/admin/expert/fulledit_dapnetapi.php index 37ccefc..909cf15 100644 --- a/admin/expert/fulledit_dapnetapi.php +++ b/admin/expert/fulledit_dapnetapi.php @@ -1,26 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
/tmp/jsADGHwf9sj294.tmp'); + exec('echo "USER=" >> /tmp/jsADGHwf9sj294.tmp'); + exec('echo "PASS=" >> /tmp/jsADGHwf9sj294.tmp'); + exec('echo "TRXAREA=" >> /tmp/jsADGHwf9sj294.tmp'); } -exec('sudo chown www-data:www-data ' . escapeshellarg($filepath)); -exec('sudo chmod 600 ' . escapeshellarg($filepath)); + +//Do some file wrangling... +exec('sudo chmod 664 /tmp/jsADGHwf9sj294.tmp'); + +//ini file to open +$filepath = '/tmp/jsADGHwf9sj294.tmp'; //after the form submit if($_POST) { - $data = $_POST; - //update ini file, call function - update_ini_file($data, $filepath); + $data = $_POST; + //update ini file, call function + update_ini_file($data, $filepath); } //this is the function going to update your ini file - function update_ini_file($data, $filepath) - { - $content = ""; + function update_ini_file($data, $filepath) { + $content = ""; - //parse the ini file to get the sections - //parse the ini file using default parse_ini_file() PHP function - $parsed_ini = parse_ini_file($filepath, true); + //parse the ini file to get the sections + //parse the ini file using default parse_ini_file() PHP function + $parsed_ini = parse_ini_file($filepath, true); - foreach($data as $section=>$values) { - // UnBreak special cases - $section = str_replace("_", " ", $section); - $content .= "[".$section."]\n"; - //append the values - foreach($values as $key=>$value) { - // Strip CR/LF from values before they land in the INI - // file. The save handler writes `$key=$value\n` and a - // newline inside $value would split the value into a - // new INI line, allowing injection of arbitrary - // additional keys (e.g. `value=foo\nDEBUG=1`). On a - // single-operator device the practical risk is low - // but the sanitiser is one line. - $value = str_replace(array("\r", "\n"), "", (string)$value); - $content .= $key."=".$value."\n"; - } - $content .= "\n"; - } + foreach($data as $section=>$values) { + // UnBreak special cases + $section = str_replace("_", " ", $section); + $content .= "[".$section."]\n"; + //append the values + foreach($values as $key=>$value) { + $content .= $key."=".$value."\n"; + } + $content .= "\n"; + } - //write it into file - if (!$handle = fopen($filepath, 'w')) { - return false; - } + //write it into file + if (!$handle = fopen($filepath, 'w')) { + return false; + } - $success = fwrite($handle, $content); - fclose($handle); + $success = fwrite($handle, $content); + fclose($handle); - // Atomic install: mode + owner set in one syscall sequence. - // /etc/dapnetapi.key holds DAPNET credentials — mode 600 keeps - // them readable only by www-data. Owner left as www-data - // because the dapnetgateway daemon reads via the dashboard - // (and dashboard reads it directly without sudo elsewhere); - // see fulledit_bmapikey.php for the same rationale. - exec('sudo mount -o remount,rw /'); - exec('sudo install -m 600 -o www-data -g www-data ' - . escapeshellarg($filepath) . ' /etc/dapnetapi.key'); - exec('sudo mount -o remount,ro /'); + // Updates complete - copy the working file back to the proper location + exec('sudo mount -o remount,rw /'); // Make rootfs writable + exec('sudo cp /tmp/jsADGHwf9sj294.tmp /etc/dapnetapi.key'); // Move the file back + exec('sudo chmod 644 /etc/dapnetapi.key'); // Set the correct runtime permissions + exec('sudo chown root:root /etc/dapnetapi.key'); // Set the owner + exec('sudo mount -o remount,ro /'); // Make rootfs read-only - return $success; - } + return $success; + } //parse the ini file using default parse_ini_file() PHP function $parsed_ini = parse_ini_file($filepath, true); echo '
'."\n"; -echo csrf_field_html()."\n"; - foreach($parsed_ini as $section=>$values) { - // Same hardening as edit_mmdvmhost.php (#23): escape every INI - // section / key / value before HTML interpolation. The save - // handler writes POST bytes verbatim so legitimate values - // (including any with `"` or `<`) round-trip byte-identically. - $sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8'); - // keep the section as hidden text so we can update once the form submitted - echo "\n"; - echo "\n"; - echo "\n"; - // print all other values as input fields, so can edit. - // note the name='' attribute it has both section and key - foreach($values as $key=>$value) { - $keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'); - $valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8'); - if (($key == "Options") || ($value)) { - echo "\n"; - } - elseif (($key == "Display") && ($value == '')) { - echo "\n"; - } - else { - echo "\n"; - } - } - echo "
$sectionHtml
$keyHtml
$keyHtml
$keyHtml
\n"; - echo ''."\n"; - echo "
\n"; - } + foreach($parsed_ini as $section=>$values) { + // keep the section as hidden text so we can update once the form submitted + echo "\n"; + echo "
\n"; + echo "

$section

\n"; + // print all other values as input fields, so can edit. + // note the name='' attribute it has both section and key + foreach($values as $key=>$value) { + if (($key == "Options") || ($value)) { + echo "
$key
\n"; + } + elseif (($key == "Display") && ($value == '')) { + echo "
$key
\n"; + } + else { + echo "
$key
\n"; + } + } + echo "
\n"; + echo ''."\n"; + echo "
\n"; + } echo "
"; ?>
-
- diff --git a/admin/expert/fulledit_dmrgateway.php b/admin/expert/fulledit_dmrgateway.php index 2ffdb81..2468c55 100644 --- a/admin/expert/fulledit_dmrgateway.php +++ b/admin/expert/fulledit_dmrgateway.php @@ -1,28 +1,4 @@ .tmp then sudo-copied back to /etc/dmrgateway. - * Restarts BOTH mmdvmhost.service AND dmrgateway.service after save. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); //Load the Pi-Star Release file @@ -41,67 +17,70 @@ require_once('../config/version.php'); - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
+

DMR Gateway (Full Edit)

+
- -
- +
+
+
-
- diff --git a/admin/expert/fulledit_pistar-remote.php b/admin/expert/fulledit_pistar-remote.php index aef4a4d..cd382c7 100644 --- a/admin/expert/fulledit_pistar-remote.php +++ b/admin/expert/fulledit_pistar-remote.php @@ -1,26 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
+

PiStar-Remote (Full Edit)

+
- -
- +
+
+
-
- diff --git a/admin/expert/fulledit_rssidat.php b/admin/expert/fulledit_rssidat.php index 696828a..fe40de2 100644 --- a/admin/expert/fulledit_rssidat.php +++ b/admin/expert/fulledit_rssidat.php @@ -1,26 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
+

RSSI Dat (Full Edit)

+
- -
- +
+
+
-
- diff --git a/admin/expert/fulledit_wpaconfig.php b/admin/expert/fulledit_wpaconfig.php index 93a923d..27ec8b9 100644 --- a/admin/expert/fulledit_wpaconfig.php +++ b/admin/expert/fulledit_wpaconfig.php @@ -1,27 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
.tmp as a symlink to a target -// they control reading and have our `sudo cp` follow it. -$filepath = tempnam('/tmp', 'pistar-edit-'); -register_shutdown_function(function() use ($filepath) { @unlink($filepath); }); -exec('sudo cp /etc/wpa_supplicant/wpa_supplicant.conf ' . escapeshellarg($filepath)); -exec('sudo chown www-data:www-data ' . escapeshellarg($filepath)); -exec('sudo chmod 600 ' . escapeshellarg($filepath)); - if(isset($_POST['data'])) { - // Write submitted data into the staging file. + // File Wrangling + exec('sudo cp /etc/wpa_supplicant/wpa_supplicant.conf /tmp/k45s7h5s9k3.tmp'); + exec('sudo chown www-data:www-data /tmp/k45s7h5s9k3.tmp'); + exec('sudo chmod 664 /tmp/k45s7h5s9k3.tmp'); + + // Open the file and write the data + $filepath = '/tmp/k45s7h5s9k3.tmp'; $fh = fopen($filepath, 'w'); fwrite($fh, $_POST['data']); fclose($fh); - // Atomic install: mode + owner set in one syscall sequence. - // wpa_supplicant.conf carries the WPA PSK in cleartext as - // `psk=…hex…` — mode 600 root:root keeps every other local - // user (and any sandbox-escape from another service) from - // reading it. wpa_supplicant runs as root, so the daemon's - // own access is unaffected. exec('sudo mount -o remount,rw /'); - exec('sudo install -m 600 -o root -g root ' - . escapeshellarg($filepath) . ' /etc/wpa_supplicant/wpa_supplicant.conf'); + exec('sudo cp /tmp/k45s7h5s9k3.tmp /etc/wpa_supplicant/wpa_supplicant.conf'); + exec('sudo chmod 644 /etc/wpa_supplicant/wpa_supplicant.conf'); + exec('sudo chown www-data:www-data /etc/wpa_supplicant/wpa_supplicant.conf'); exec('sudo mount -o remount,ro /'); -} -// Re-read for the form's textarea. -$fh = fopen($filepath, 'r'); -$theData = fread($fh, filesize($filepath)); + // Re-open the file and read it + $fh = fopen($filepath, 'r'); + $theData = fread($fh, filesize($filepath)); + +} else { + // File Wrangling + exec('sudo cp /etc/wpa_supplicant/wpa_supplicant.conf /tmp/k45s7h5s9k3.tmp'); + exec('sudo chown www-data:www-data /tmp/k45s7h5s9k3.tmp'); + exec('sudo chmod 664 /tmp/k45s7h5s9k3.tmp'); + + // Open the file and read it + $filepath = '/tmp/k45s7h5s9k3.tmp'; + $fh = fopen($filepath, 'r'); + $theData = fread($fh, filesize($filepath)); +} fclose($fh); ?> +

WiFi Config (Full Edit)

+
- -
- +
+
+
-
- diff --git a/admin/expert/index.php b/admin/expert/index.php index b4a8022..a5e069a 100644 --- a/admin/expert/index.php +++ b/admin/expert/index.php @@ -1,21 +1,4 @@ - - + + - Pi-Star - Digital Voice Dashboard - Expert Editor + CDN - Digital Voice Dashboard - Expert Editor -
- - - -
Expert Editors
-

**WARNING**

- Pi-Star Expert editors have been created to make editing some of the extra settings in the
- config files more simple, allowing you to update some areas of the config files without the
+

Expert Editors

+
+
+ **WARNING**

+ CDN Expert editors have been created to make editing some of the extra settings in the + config files more simple, allowing you to update some areas of the config files without the need to login to your Pi over SSH.

- Please keep in mind when making your edits here, that these config files can be updated by
- the dashboard, and that your edits can be over-written. It is assumed that you already know
- what you are doing editing the files by hand, and that you understand what parts of the files
+ Please keep in mind when making your edits here, that these config files can be updated by + the dashboard, and that your edits can be over-written. It is assumed that you already know + what you are doing editing the files by hand, and that you understand what parts of the files are maintained by the dashboard.

- With that warning in mind, you are free to make any changes you like, for help come to the Facebook
+ With that warning in mind, you are free to make any changes you like, for help come to the Facebook group (link at the bottom of the page) and ask for help if / when you need it.
- 73 and enjoy your Pi-Star experiance.
- Pi-Star UK Team.
-
-
+ 73 and enjoy your CDN experiance.
+ CDN Team. +
+ - - - diff --git a/admin/expert/jitter_test.php b/admin/expert/jitter_test.php index 2f5df90..c68bcda 100644 --- a/admin/expert/jitter_test.php +++ b/admin/expert/jitter_test.php @@ -1,23 +1,4 @@ ` on the - * device; output streams to /var/log/pi-star/pi-star_icmptest.log - * which this page tails via AJAX (jquery-timing $.repeat). - * - * Uses system()/exec() rather than the staged-write pattern — no - * file edits, just a privileged background process. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); // Load the Pi-Star Release file @@ -37,9 +18,8 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/jitter_test.php") { } else { $target = "DMR+"; } if (!isset($_GET['ajax'])) { - // truncate creates+clears the log file in one synchronous call — - // see admin/update.php for the full rationale. - system('sudo truncate -s 0 /var/log/pi-star/pi-star_icmptest.log'); + system('sudo touch /var/log/pi-star/pi-star_icmptest.log > /dev/null 2>&1 &'); + system('sudo echo "" > /var/log/pi-star/pi-star_icmptest.log > /dev/null 2>&1 &'); system('sudo /usr/local/sbin/pistar-jittertest '.$target.' > /dev/null 2>&1 &'); } @@ -88,13 +68,13 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/jitter_test.php") { - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?> @@ -114,20 +94,13 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/jitter_test.php") { -
- - - -
Test Running
Starting test, please wait...
+

Jitter Test Running

+
+
Starting test, please wait...
-
@@ -135,3 +108,4 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/jitter_test.php") { diff --git a/admin/expert/modem_fw_upgrade.php b/admin/expert/modem_fw_upgrade.php index 557238b..dc667a0 100644 --- a/admin/expert/modem_fw_upgrade.php +++ b/admin/expert/modem_fw_upgrade.php @@ -1,31 +1,4 @@ ` to flash the selected one. Output streams - * to /var/log/pi-star/pi-star_modemflash.log; tailed via AJAX. - * - * The selected variant is run through escapeshellarg() before being - * passed to the upgrade script (defence-in-depth — the picklist is - * already constrained to script-reported names). - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// CSRF protection — see config/csrf.php for the full rationale. -// Must run BEFORE any output: bootstraps the session on GET (so -// Set-Cookie ships) and rejects forged POSTs cleanly with 403 -// before any state change (sed-i, fopen+fwrite, sudo cp, etc.). -csrf_verify(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); // Load the Pi-Star Release file @@ -42,61 +15,29 @@ setlocale(LC_ALL, "LC_CTYPE=en_GB.UTF-8;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_M if ($_SERVER["PHP_SELF"] == "/admin/expert/modem_fw_upgrade.php") { if ($_SERVER['REQUEST_METHOD'] === 'POST') { - if (isset($_POST['modem'])) { - // Whitelist-validate against the canonical modem list that - // pistar-modemupgrade itself reports. The script is the - // authoritative source of "what modem variants this device - // knows how to flash" — POSTed values that don't appear in - // that list are silently dropped (the operator just sees no - // flash happen). escapeshellarg() below is still defence- - // in-depth at the shell layer; this is the application-layer - // gate that stops the script from being invoked with - // attacker-controlled args at all. Mirrors the mmdvmcal - // command whitelist in admin/calibration.php. - $validModems = array_filter(array_map('trim', - explode("\n", (string)shell_exec('sudo /usr/local/sbin/pistar-modemupgrade list')) - )); - if (in_array($_POST['modem'], $validModems, true)) { - $selectedOption = $_POST['modem']; - } else { - error_log('Pi-Star modem_fw_upgrade.php: rejected modem=' . substr((string)$_POST['modem'], 0, 64)); - } - } + if (isset($_POST['modem'])) { + $selectedOption = $_POST['modem']; + } } if (!isset($_GET['ajax'])) { - // truncate creates+clears the log file in one synchronous call — - // see admin/update.php for the full rationale. - system('sudo truncate -s 0 /var/log/pi-star/pi-star_modemflash.log'); - // No `NP=1` env-var prefix: the path-scoped sudoers refuses - // env-var pass-through without a SETENV: tag, so `sudo NP=1 - // pistar-modemupgrade …` was rejected outright with "you are - // not allowed to set the following environment variables: NP" - // and the flash silently never started. The wrapper now - // auto-detects non-interactive mode via `[ -t 0 ]` (it's - // backgrounded here with no controlling terminal), so the - // explicit env var is no longer needed. - if (isset($selectedOption)) { system('sudo /usr/local/sbin/pistar-modemupgrade ' . escapeshellarg($selectedOption) . ' > /dev/null 2>&1 &'); } + system('sudo touch /var/log/pi-star/pi-star_modemflash.log > /dev/null 2>&1 &'); + system('sudo echo "" > /var/log/pi-star/pi-star_modemflash.log > /dev/null 2>&1 &'); + if (isset($selectedOption)) { system('sudo NP=1 /usr/local/sbin/pistar-modemupgrade ' . escapeshellarg($selectedOption) . ' > /dev/null 2>&1 &'); } } // passed sanity chk. header('Cache-Control: no-cache'); - // csrf_verify() at the top of the file already started the - // session via csrf_session_start(). Calling session_start() a - // second time emits a PHP Notice on PHP 8.x ("Ignoring - // session_start() because a session is already active") that - // gets logged to nginx error.log on every page load. The - // existing $_SESSION['update_offset'] log-tail logic below - // works unchanged against the already-active session. + session_start(); if (!isset($_GET['ajax'])) { - if (file_exists('/var/log/pi-star/pi-star_modemflash.log')) { - $_SESSION['update_offset'] = filesize('/var/log/pi-star/pi-star_modemflash.log'); - } else { - $_SESSION['update_offset'] = 0; + if (file_exists('/var/log/pi-star/pi-star_modemflash.log')) { + $_SESSION['update_offset'] = filesize('/var/log/pi-star/pi-star_modemflash.log'); + } else { + $_SESSION['update_offset'] = 0; } } - + if (isset($_GET['ajax'])) { if (!file_exists('/var/log/pi-star/pi-star_modemflash.log')) { exit(); @@ -113,10 +54,10 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/modem_fw_upgrade.php") { else { fseek($handle, 0, SEEK_END); $_SESSION['update_offset'] = ftell($handle); - } + } exit(); } - + // Get the firmware version if (file_exists('/usr/local/bin/firmware/version.txt')) { $versionData = parse_ini_file('/usr/local/bin/firmware/version.txt', true); @@ -140,32 +81,30 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/modem_fw_upgrade.php") { - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - Modem FW ".$lang['update'];?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - Modem FW ".$lang['update'];?> -
- +

Modem Firmware Upgrade Utility

- - - -
Modem Firmware Upgrade Utility
-
-

Modem Firmware Upgrade Utility

-

This tool will attempt to upgrade your selected modem to the latest version available firmware version:
-

-

When ready, select your modem type below and click, "Upgrade Modem". Do not interrupt the process or
- navigate away from the page while the process is running.

-

Please understand what you are doing, as well as the risks associated with flashing your modem.

-

(IMPORTANT: Please note, we are not firmware developers, and we offer no support for firmware.
- We provide utilities to update the firmware. For firmware support, you will need to utilise other
- support resources from the firmware developers/maintainers or the web.)

-
+
+

This tool will attempt to upgrade your selected modem to the latest version available firmware version:
+

+

When ready, select your modem type below and click, "Upgrade Modem". Do not interrupt the process or
+ navigate away from the page while the process is running.

+

Please understand what you are doing, as well as the risks associated with flashing your modem.

+

(IMPORTANT: Please note, we are not firmware developers, and we offer no support for firmware.
+ We provide utilities to update the firmware. For firmware support, you will need to utilise other
+ support resources from the firmware developers/maintainers or the web.)

'MMDVM_HS_GENERIC_DUPLEX (14.7456MHz TCXO) GPIO', 'hs_hat_generic_duplex-usb' => 'MMDVM_HS_GENERIC_DUPLEX (14.7456MHz TCXO) USB', 'hs_hat_nano_hotspot' => 'Nano_hotSPOT by BI7JTA (14.7456MHz TCXO) GPIO', - 'hs_hat_nano_hotspot-duplex' => 'Nano_hotSPOT Dual by VR2VYE & BI7JTA (14.7456MHz TCXO) GPIO', 'dvmega_gpio' => 'DV-Mega Raspberry Pi Hat (Single or Dual Band) GPIO', 'dvmega_usb_uno' => 'DV-Mega Arduino Uno Shield USB (ttyUSB0)', 'dvmega_usb_mega' => 'DV-Mega Arduino Mega Shield USB (ttyUSB0)', @@ -249,15 +181,14 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/modem_fw_upgrade.php") { // Create the select element echo '

'; - echo csrf_field_html(); echo ''; echo ''; echo ''; echo '

'; @@ -265,33 +196,21 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/modem_fw_upgrade.php") { echo '

Error executing the command.

'; } ?> - -
-
- Modem Flash/Upgrade Output -
Starting FW Upgrade, please wait...
- +
+
Starting FW Upgrade, please wait...
-
+ diff --git a/admin/expert/ssh_access.php b/admin/expert/ssh_access.php index 3c89d1c..cec961f 100644 --- a/admin/expert/ssh_access.php +++ b/admin/expert/ssh_access.php @@ -1,23 +1,4 @@ . Uses - * setSecurityHeadersAllowDifferentPorts() to relax the default same- - * origin frame restriction so the iframe can target a non-80 port on - * the same host. - * - * No file edits, no privileged calls — pure UI wrapper. - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeadersAllowDifferentPorts(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('../config/language.php'); // Load the Pi-Star Release file @@ -32,37 +13,6 @@ if (file_exists('/etc/default/shellinabox')) { $shellPort = exec($getPortCommand); } -// HTTP_HOST is client-controllable (any HTTP client can send any -// `Host:` header). Echoing it raw into HTML attributes — as the -// iframe `src` and the anchor `href` below do — gives a passing -// attacker a reflected XSS surface: a request with a crafted Host -// header would render an iframe pointing at attacker-controlled -// content inside this page. -// -// Two-layer defence: -// 1. Strip everything that isn't a hostname character. The set -// `[a-zA-Z0-9.\-\[\]:]` covers DNS names, IPv4 dotted-quad, -// IPv6 bracketed literals, and the optional `:port` suffix. -// Anything else (CRLF, `<`, `"`, `'`, semicolons, spaces, -// parens, slashes) is dropped — the regex is what closes -// the XSS / response-splitting class. -// 2. htmlspecialchars on top, so even if the regex were -// relaxed in the future the value still can't break out -// of the `"…"` HTML attribute it lands in. -$shellHost = preg_replace( - '/[^a-zA-Z0-9.\-\[\]:]/', - '', - isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '' -); -if ($shellHost === '') { - // Pathological case: HTTP_HOST contained nothing usable. Fall - // back to the LAN IP that nginx listens on rather than emitting - // a broken iframe `src=":port"`. - $shellHost = 'localhost'; -} -$shellHostHtml = htmlspecialchars($shellHost, ENT_QUOTES, 'UTF-8'); -$shellPortHtml = htmlspecialchars((string)(isset($shellPort) ? $shellPort : ''), ENT_QUOTES, 'UTF-8'); - // Sanity Check that this file has been opened correctly if ($_SERVER["PHP_SELF"] == "/admin/expert/ssh_access.php") { ?> @@ -75,40 +25,33 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/ssh_access.php") { - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - SSH";?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - SSH";?> -
- - - -
SSH - Pi-Star
+

SSH - CDN

+
+
"; + echo ""; } else { echo "SSH Feature not yet installed"; } ?> -
- Click here for fullscreen SSH client
\n"; } ?>
- \n"; } ?> +
@@ -116,3 +59,4 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/ssh_access.php") { diff --git a/admin/expert/upgrade.php b/admin/expert/upgrade.php index e39b89e..94b1160 100644 --- a/admin/expert/upgrade.php +++ b/admin/expert/upgrade.php @@ -1,28 +1,4 @@ ` ran as www-data, - // defeating the sudo on the truncation step). - system('sudo truncate -s 0 /var/log/pi-star/pi-star_upgrade.log'); - system('sudo /usr/local/sbin/pistar-upgrade > /dev/null 2>&1 &'); - } - - // Sanity Check Passed. - header('Cache-Control: no-cache'); - // session_start() is no longer called here — csrf_verify() at - // the top already started the session via csrf_session_start(). - // The existing $_SESSION['update_offset'] log-tail logic below - // works unchanged against the already-active session. - - // Initialize session offset only if upgrade has been confirmed - if (!isset($_GET['ajax']) && !empty($_POST) && isset($_POST['confirm_update'])) { - //unset($_SESSION['update_offset']); - if (file_exists('/var/log/pi-star/pi-star_upgrade.log')) { - $_SESSION['update_offset'] = filesize('/var/log/pi-star/pi-star_upgrade.log'); - } else { - $_SESSION['update_offset'] = 0; - } - } - + // Web-based upgrades have been disabled. if (isset($_GET['ajax'])) { - //session_start(); - if (!file_exists('/var/log/pi-star/pi-star_upgrade.log')) { - exit(); - } - - $handle = fopen('/var/log/pi-star/pi-star_upgrade.log', 'rb'); - if (isset($_SESSION['update_offset'])) { - fseek($handle, 0, SEEK_END); - if ($_SESSION['update_offset'] > ftell($handle)) //log rotated/truncated - $_SESSION['update_offset'] = 0; //continue at beginning of the new log - $data = stream_get_contents($handle, -1, $_SESSION['update_offset']); - $_SESSION['update_offset'] += strlen($data); - echo nl2br($data); - } - else { - fseek($handle, 0, SEEK_END); - $_SESSION['update_offset'] = ftell($handle); - } - exit(); + exit(); } + header('Cache-Control: no-cache'); ?> @@ -94,79 +27,28 @@ if ($_SERVER["PHP_SELF"] == "/admin/expert/upgrade.php") { - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?> - - - - - -
- - - - -
Upgrade Running
Starting upgrade, please wait...
- -
" method="post"> - - - - - - - - -
Upgrade
-

- This will upgrade your Pi-Star installation to the latest version.
-
- The upgrade process may take several minutes to complete.
- Please do not interrupt the process or power off your system during the upgrade. -

- -
-
- +

Upgrade Disabled

+
+
Web-based upgrades have been disabled on this system.
-
diff --git a/admin/images b/admin/images deleted file mode 100644 index 5e67573..0000000 --- a/admin/images +++ /dev/null @@ -1 +0,0 @@ -../images \ No newline at end of file diff --git a/admin/images/20green.png b/admin/images/20green.png new file mode 100644 index 0000000000000000000000000000000000000000..824526690f42b41316a92fcef684a5e9b664a8f6 GIT binary patch literal 1247 zcmeHG?MqW}7(LTsKPT!<77P>fnqb$|yhNB{hS&MBi*C9Ub00z&Wh`t#W4)`KB zJ3k%F;sF5=fkZ$8WPsf@0cOAgusu8A0GxmeXahQdF2Dl}07JkyFagW}i@+-21t^Gy z5Rnjx5E(=!WSkH$A(U_e$4MMF&T(FjqYN62Rij}{d0ymsBhNc{ewF9FJkJ~|2$CS! z1%dJco2e+uqR5ygCR#;_N)nZ2r!0G9nMyL1jf+MjWiXql$wbX&YB5u*Wx!&YFk2{t z#kvKD-D`J@+a1*9oN&0PvyHmCXea$&|6~Hb@B2E~gB00}`lEj<02t~OL4YDar%la2 zGhO+@&u}hYt*iWyE+1BWBl5ERj0JycyW^UO;lQ}%|qe;8iR{r)z6*HG5q zaX-`kwjsJPqwHS$_u;9r-njGEHyWe5cN^RV%_UdsmJWwKtQ{Lk4IR#V(ibJ3{qZ1n zxqMr+&q7P!^W!Jx=W0x;-5*9zyA_4|7l!B8SAMGFXPvKhK3@M-?lOF-NfLVAWK4ym zwH7LUtD`(I0k`93Q}RC9oBU1|Ol;h_kx*)@bbjnj8r4Q#*bMVre3|kzI9V+@lCg(; zj$LwYDh5l659#I-cDTY~mN=KKrCeFpx;)vGlbv=Y^j+|&ijl#|WAuQb*wNf`?Vx|} a<=VAfwg|n?rAKZBOCP#)z4n$=T=xh0$wS)! literal 0 HcmV?d00001 diff --git a/admin/images/20red.png b/admin/images/20red.png new file mode 100644 index 0000000000000000000000000000000000000000..6cde8d8ae3ea24b00e24163b87a33973e34a997f GIT binary patch literal 1207 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc3?z4jzqJQa>?NMQuI#tixw!;nJXu%`fI^%F z9+AZi40;kE%&4_WU4emtnIXU@#1$x_$iScpL>wH33=D<>0+tL6PC&%L;Upm7#lYYt zApx`{NI)QpfgzcJA)A2#XizZ+N3n!NH3LJnfItfaLyLew4+BGwqT&<=hB*ujOBoo} zGB9ifB1Of$3=DfMEsrrUoC6{bj&n{<*BBVC85&-5a=ORB@EnLVHQzHZycZDo&cN`U zgX24pVQKlFf#E*~$A1BV{}K}a6&3$$YW_Dg{0|g&a{BM(^*<=+e|Gl&>gxYJJ^$y- z`9BIqLx9{6IRCfcJTQYel?3?(lWPWCAA^gS0MIaoKb|g*Ar-fBFJ${S8;Gza^{HmuP3>et1p7;g8Q(ljkjyxKI}!YHV68)Si|ev&!w%vb$l2=cWioHJo+pYfN%G#BkxK z#`VRHhTaBkkDqONviN0Ei|yYf4dSfrB0M^78S4tCZJgs+G;1PD^}P?i^4q2`Ej65B z%6DYBO5>4*?<>!l?5dn{q?;kRB>msn&9B$hw$xm=l>Jos?`VAU4Y%uimiXC%0>abP K&t;ucLK6U}c2BVY literal 0 HcmV?d00001 diff --git a/admin/images/download.png b/admin/images/download.png new file mode 100644 index 0000000000000000000000000000000000000000..bd1b12df505ced3649fd0013f83b20afed770273 GIT binary patch literal 12380 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 literal 0 HcmV?d00001 diff --git a/admin/images/favicon.ico b/admin/images/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b9f278c2042b1b0dd43fe68407f404312c57da0e GIT binary patch literal 1150 zcmbVMO;5r=5M2{*UWfFn;z zym>PZQl+l+lglY>@73eAQg=$J2mNZ7_GEs&DWzk#H`&W~ZRpHO)0Dl>&o5+I7N57< z?U~H;F2NTHMXJ|LPD<1NPDRwiv`z!5q!JtlIwm^zaQ%Ur>x;%Frd+B#OLvNOub&8 z=L>?~Ne{J;8rMf3>-C!BsFm!r0B00Mx*v~cJmki2Q>|7Bd~qBzpX<7sug97Nel|~r z_o>;m_x#eo<2cmqc6I-Ko)2|OrB^DK-)KIcQ<5YcLtW$vzuU!DD literal 0 HcmV?d00001 diff --git a/admin/images/index.php b/admin/images/index.php new file mode 100644 index 0000000..e69de29 diff --git a/admin/images/reboot.png b/admin/images/reboot.png new file mode 100644 index 0000000000000000000000000000000000000000..1893f3a941478534212f9e3788ab113c3d683e24 GIT binary patch literal 34314 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 z⪼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 Y2Or^#b~T6)s{jB107*qoM6N<$f)!lHJOBUy literal 0 HcmV?d00001 diff --git a/admin/images/restore.png b/admin/images/restore.png new file mode 100644 index 0000000000000000000000000000000000000000..d0c17360b679fc3455a96ee6aa954037a069a364 GIT binary patch literal 13801 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 Chq`3| literal 0 HcmV?d00001 diff --git a/admin/images/shutdown.png b/admin/images/shutdown.png new file mode 100644 index 0000000000000000000000000000000000000000..838495be1383cd87c18244430322745b15688178 GIT binary patch literal 22498 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 0) + $configs[$key] = $value; + } + +} +$progname = basename($_SERVER['SCRIPT_FILENAME'],".php"); +$rev=$version; +//$MYCALL=strtoupper($callsign); +$MYCALL=strtoupper($configs['gatewayCallsign']); + +// Check if the config file exists +if (file_exists('/etc/pistar-css.ini')) { + $piStarCssFile = '/etc/pistar-css.ini'; + if (fopen($piStarCssFile,'r')) { $piStarCss = parse_ini_file($piStarCssFile, true); } + if ($piStarCss['BannerH1']['Enabled']) { + $piStarCssBannerH1 = $piStarCss['BannerH1']['Text']; + } + if ($piStarCss['BannerExtText']['Enabled']) { + $piStarCssBannerExtTxt = $piStarCss['BannerExtText']['Text']; + } +} + +//Load the Pi-Star Release file +$pistarReleaseConfig = '/etc/pistar-release'; +$configPistarRelease = array(); +$configPistarRelease = parse_ini_file($pistarReleaseConfig, true); +?> + + + + + + + + \n"; ?> + + + + + + + + + + <?php echo "$MYCALL"." - ".$lang['digital_voice']." ".$lang['dashboard'];?> + + + + + + +
+ + +'."\n"; + echo ''."\n"; + echo '
'."\n"; + include 'dstarrepeater/system.php'; // Basic System Info + echo '
'."\n"; + echo '
'."\n"; + } +// First lets figure out if we are in MMDVMHost mode, or dstarrepeater mode; +if (file_exists('/etc/dstar-radio.mmdvmhost')) { + include 'config/config.php'; // MMDVMDash Config + include_once 'mmdvmhost/tools.php'; // MMDVMDash Tools + + function getMMDVMConfigFileContent() { + // loads /etc/mmdvmhost into array for further use + $conf = array(); + if ($configs = @fopen('/etc/mmdvmhost', 'r')) { + while ($config = fgets($configs)) { + array_push($conf, trim ( $config, " \t\n\r\0\x0B")); + } + fclose($configs); + } + return $conf; + } + $mmdvmconfigfile = getMMDVMConfigFileContent(); + + $dashboardRowOpen = true; + echo '
'."\n"; // Pairs .nav + .content so they stretch to equal height + echo ''."\n"; + + echo '
'."\n"; + + $testMMDVModeDSTARnet = getConfigItem("D-Star Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeDSTARnet == 1 ) { // If D-Star network is enabled, add these extra features. + + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Option + echo ''."\n"; + echo ''."\n"; + echo '
'."\n"; + + include 'dstarrepeater/link_manager.php'; // D-Star Link Manager + echo "
\n"; + } + + echo ''."\n"; + echo '
'."\n"; + include 'dstarrepeater/css_connections.php'; // dstarrepeater gateway config + echo '
'."\n"; + } + + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Option + echo ''."\n"; + echo '
'."\n"; + include 'mmdvmhost/bm_links.php'; // BM Links + echo '
'."\n"; + } + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Options + include 'mmdvmhost/bm_manager.php'; // BM DMR Link Manager + } + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Option + echo ''."\n"; + echo '
'."\n"; + include 'mmdvmhost/tgif_links.php'; // TGIF Links + echo '
'."\n"; + } + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Options + include 'mmdvmhost/tgif_manager.php'; // TGIF DMR Link Manager + } + $testMMDVModeYSFnet = getConfigItem("System Fusion Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeYSFnet == 1 ) { // If YSF network is enabled, add these extra features. + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Option + include 'mmdvmhost/ysf_manager.php'; // YSF Links + } + } + $testMMDVModeP25net = getConfigItem("P25 Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeP25net == 1 ) { // If P25 network is enabled, add these extra features. + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Option + include 'mmdvmhost/p25_manager.php'; // P25 Links + } + } + $testMMDVModeNXDNnet = getConfigItem("NXDN Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeNXDNnet == 1 ) { // If NXDN network is enabled, add these extra features. + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Option + include 'mmdvmhost/nxdn_manager.php'; // NXDN Links + } + } + $testMMDVModeM17net = getConfigItem("M17 Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeM17net == 1 ) { // If NXDN network is enabled, add these extra features. + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Option + include 'mmdvmhost/m17_manager.php'; // M17 Links + } + } + echo ''."\n"; + echo '
'."\n"; + include 'mmdvmhost/lh.php'; // MMDVMDash Last Herd + echo '
'."\n"; + echo "
\n"; + echo '
'."\n"; + include 'mmdvmhost/localtx.php'; // MMDVMDash Local Trasmissions + echo '
'."\n"; + + // If POCSAG is enabled, show the information pannel + $testMMDVModePOCSAG = getConfigItem("POCSAG Network", "Enable", $mmdvmconfigfile); + if ( $testMMDVModePOCSAG == 1 ) { + echo ''."\n"; + echo "
\n"; + echo '
'."\n"; + include 'mmdvmhost/pages.php'; // POCSAG Messages + echo '
'."\n"; + } + +} elseif (file_exists('/etc/dstar-radio.dstarrepeater')) { + echo '
'."\n"; + include 'dstarrepeater/gateway_software_config.php'; // dstarrepeater gateway config + echo ''."\n"; + echo '
'."\n"; + echo ''."\n"; + echo '
'."\n"; + if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Admin Only Options + include 'dstarrepeater/link_manager.php'; // D-Star Link Manager + echo "
\n"; + } + + echo ''."\n"; + echo '
'."\n"; + include 'dstarrepeater/css_connections.php'; // dstarrepeater gateway config + echo '
'."\n"; + + echo ''."\n"; + echo '
'."\n"; + include 'dstarrepeater/last_herd.php'; //dstarrepeater Last Herd + echo '
'."\n"; + echo "
\n"; + echo '
'."\n"; + include 'dstarrepeater/local_tx.php'; //dstarrepeater Local Transmissions + echo '
'."\n"; + echo '
'."\n"; + +} else { + echo '
'."\n"; + //We dont know what mode we are in - fail... + echo "

未定义工作模式...

\n"; + echo ''."\n"; +} +?> +
+\n"; } ?> + +
+ + + + diff --git a/admin/lang b/admin/lang deleted file mode 100644 index 497aa1a..0000000 --- a/admin/lang +++ /dev/null @@ -1 +0,0 @@ -../lang/ \ No newline at end of file diff --git a/admin/lang/catalan_es.php b/admin/lang/catalan_es.php new file mode 100644 index 0000000..2500760 --- /dev/null +++ b/admin/lang/catalan_es.php @@ -0,0 +1,158 @@ + "Veu Digital", + "configuration" => "Configuració", + "dashboard_for" => "Tauler de control de", + // Banner links + "dashboard" => "Tauler de Control", + "admin" => "Administrar", + "power" => "Reiniciar/Apagar", + "update" => "Actualitzar", + "backup_restore" => "Fer/Restaurar còpia seguretat", + "factory_reset" => "Restaurar estat de fàbrica", + "live_logs" => "Informes/Logs", + // Config page section headdings + "hardware_info" => "Informació del maquinari", + "control_software" => "Control de programari", + "mmdvmhost_config" => "Configuració de MMDVMHost", + "general_config" => "Configuració General", + "dmr_config" => "Configuració de DMR", + "dstar_config" => "Configuració de DSTAR", + "ysf_config" => "Configuració de Yaesu C4FM fusion", + "p25_config" => "Configuració de P25", + "nxdn_config" => "Configuració de NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuració de POCSAG", + "mobilegps_config" => "Configuració GPS mòbil", + "wifi_config" => "Configuració WIFI", + "fw_config" => "Configuració del Tallafocs", + "remote_access_pw" => "Mot clau per acccés remot", + // Config Page - Section General + "setting" => "Configuració", + "value" => "Valor", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Nom de l'amfitrió", + "kernel" => "Nucli", + "platform" => "Plataforma", + "cpu_load" => "Càrrega CPU", + "cpu_temp" => "Temperatura CPU", + // Config Page - Control Software + "controller_software" => "Controlador programari", + "controller_mode" => "Controlador de Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Mode DMR", + "d-star_mode" => "Mode D-Star", + "ysf_mode" => "Mode YSF", + "p25_mode" => "Mode P25", + "nxdn_mode" => "Mode NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Tipus de pantalla", + "mode_hangtime" => "Mode temps de suspensió", + // Config Page - General Configuration + "node_call" => "Indicatiu del Node", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Freqüència RX/TX", + "lattitude" => "Latitud", + "longitude" => "Longitud", + "town" => "Ciutat", + "country" => "País", + "url" => "URL", + "radio_type" => "Ràdio/Tipus de mòdem", + "node_type" => "Tipus de Node", + "timezone" => "Zona horària", + "dash_lang" => "Idioma del Tauler de Control", + // Config Page - DMR Configuration + "dmr_master" => "Màster DMR (MMDVMHost)", + "bm_master" => "Màster BrandMeister", + "bm_network" => "Xarxa BrandMeister", + "dmr_plus_master" => "Màster DMR+", + "dmr_plus_network" => "Xarxa DMR+", + "xlx_master" => "Màster XLX", + "xlx_enable" => "Habilitar màster XLX", + "dmr_cc" => "Codi de color DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 indicatiu de crida", + "dstar_rpt2" => "RPT2 indicatiu de crida", + "dstar_irc_password" => "mot clau d'ircDDBGateway", + "dstar_default_ref" => "Reflector predeterminat", + "aprs_host" => "Servidor d'APRS", + "dstar_irc_lang" => "Idioma d'ircDDBGateway", + "dstar_irc_time" => "Interval de Balissa", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Arrencant Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Arrencant Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Arrencant Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "Activació del GPS mòbil", + "mobilegps_port" => "Port del GPS", + "mobilegps_speed" => "Velocitat del port del GPS", + // Config Page - Firewall Configuration + "fw_dash" => "Tauler d'accés", + "fw_irc" => "ircDDBGateway Remot", + "fw_ssh" => "Accés per SSH", + // Config Page - Password + "user" => "Nom d'usuari", + "password" => "contrasenya", + "set_password" => "Establir contrasenya", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes habilitats", + "net_status" => "Estat de la xarxa", + "internet" => "Internet", + "radio_info" => "Informació de Ràdio", + "dstar_repeater" => "Repetidor D-Star", + "dstar_net" => "Xarxa D-Star", + "dmr_repeater" => "Repetidor DMR", + "dmr_master" => "Màster DMR", + "ysf_net" => "Xarxa YSF", + "p25_radio" => "Ràdio P25", + "p25_net" => "Xarxa P25", + "nxdn_radio" => "Ràdio NXDN", + "nxdn_net" => "Xarxa NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Hora", + "mode" => "Mode", + "callsign" => "Indicatiu", + "target" => "Destí", + "src" => "SRC", + "dur" => "DUR", + "loss" => "Pèrdua", + "ber" => "BER", + // POCSAG Specific + "pocsag_list" => "Activitat de passarel·la DAPNET", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Missatge", + // Dashboard - Extra Info + "group" => "Grup", + "logoff" => "Finalitzar", + "info" => "Informació", + "utot" => "UTOT", + "gtot" => "GTOT", + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Últimes 20 trucades rebudes", + "local_tx_list" => "Últimes 20 trucades rebudes via ràdio", + "active_starnet_groups" => "Grups actius Starnet", + "active_starnet_members" => "Membres actius grup Starnet", + "d-star_link_manager" => "Gestor d'enllaços D-Star", + "d-star_link_status" => "Informació d'enllaços D-Star", + "service_status" => "Estat del servei" +); +?> diff --git a/admin/lang/chinese_cn.php b/admin/lang/chinese_cn.php new file mode 100644 index 0000000..0cfd820 --- /dev/null +++ b/admin/lang/chinese_cn.php @@ -0,0 +1,157 @@ + "数字语音", + "configuration" => "配置", + "dashboard_for" => "仪表盘 -", + // Banner links + "dashboard" => "仪表盘", + "admin" => "管理", + "power" => "电源", + "update" => "更新", + "backup_restore" => "备份/恢复", + "factory_reset" => "恢复出厂设置", + "live_logs" => "日志", + // Config page section headdings + "hardware_info" => "网关硬件信息", + "control_software" => "控制软件", + "mmdvmhost_config" => "MMDVMHost 配置", + "general_config" => "常规配置", + "dmr_config" => "DMR 配置", + "dstar_config" => "D-Star 配置", + "ysf_config" => "Yaesu System Fusion 配置", + "p25_config" => "P25 配置", + "nxdn_config" => "NXDN 配置", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG 配置", + "mobilegps_config" => "Mobile GPS Configuration", + "fw_config" => "防火墙配置", + "remote_access_pw" => "远程访问密码", + // Config Page - Section General + "setting" => "设置", + "value" => "设置值", + "apply" => "应用设置", + // Config Page - Gateway Hardware Information + "hostname" => "主机名", + "kernel" => "内核", + "platform" => "平台", + "cpu_load" => "CPU 负荷", + "cpu_temp" => "CPU 温度", + // Config Page - Control Software + "controller_software" => "控制器软件", + "controller_mode" => "控制器模式", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR 模式", + "d-star_mode" => "D-Star 模式", + "ysf_mode" => "YSF 模式", + "p25_mode" => "P25 模式", + "nxdn_mode" => "NXDN 模式", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM 显示屏类型", + "mode_hangtime" => "模式停留时间", + // Config Page - General Configuration + "node_call" => "节点呼号", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "电台频率", + "lattitude" => "纬度", + "longitude" => "经度", + "town" => "城市", + "country" => "国家", + "url" => "URL", + "radio_type" => "电台/调制解调器类型", + "node_type" => "节点类型", + "timezone" => "时区", + "dash_lang" => "仪表盘语言", + // Config Page - DMR Configuration + "dmr_master" => "DMR 主机 (MMDVMHost)", + "bm_master" => "BrandMeister 主机 ", + "bm_network" => "BrandMeister 网络", + "dmr_plus_master" => "DMR+ 主机 ", + "dmr_plus_network" => "DMR+ 网络", + "xlx_master" => "XLX 主机 ", + "xlx_enable" => "XLX 主机启用", + "dmr_cc" => "DMR 彩色码", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 呼号", + "dstar_rpt2" => "RPT2 呼号", + "dstar_irc_password" => "ircDDBGateway 密码", + "dstar_default_ref" => "默认反射器", + "aprs_host" => "APRS 服务器", + "dstar_irc_lang" => "ircDDBGateway 语言", + "dstar_irc_time" => "时间通告", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF 默认服务器", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 默认服务器", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN 默认服务器", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "仪表盘访问", + "fw_irc" => "ircDDBGateway 远程", + "fw_ssh" => "SSH访问", + // Config Page - Password + "user" => "用户名", + "password" => "密码", + "set_password" => "设置密码", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "启动的模式", + "net_status" => "网络状态", + "internet" => "互联网", + "radio_info" => "电台信息", + "dstar_repeater" => "D-Star 中继", + "dstar_net" => "D-Star 网络", + "dmr_repeater" => "DMR 中继", + "dmr_master" => "DMR 主机", + "ysf_net" => "YSF 网络", + "p25_radio" => "P25 电台", + "p25_net" => "P25 网络", + "nxdn_radio" => "NXDN 电台", + "nxdn_net" => "NXDN 网络", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "时间", + "mode" => "模式", + "callsign" => "呼号", + "target" => "目标", + "src" => "源", // Short version of "Source" + "dur" => "时长", // Short version of "Duration" + "loss" => "丢失", + "ber" => "误码率", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "组", + "logoff" => "注销", + "info" => "信息", + "utot" => "用户超时", // Short for User Timeout + "gtot" => "组超时", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "网关上最后 20 个呼叫", + "local_tx_list" => "最后 20 个本地呼叫", + "active_starnet_groups" => "激活的 Starnet 组", + "active_starnet_members" => "激活的 Starnet 组成员", + "d-star_link_manager" => "D-Star 连接管理器", + "d-star_link_status" => "D-Star 连接信息", + "service_status" => "服务状态" +); +?> diff --git a/admin/lang/chinese_hk.php b/admin/lang/chinese_hk.php new file mode 100644 index 0000000..6e05669 --- /dev/null +++ b/admin/lang/chinese_hk.php @@ -0,0 +1,157 @@ + "數字語音", + "configuration" => "設定", + "dashboard_for" => "儀錶盤 -", + // Banner links + "dashboard" => "儀錶盤", + "admin" => "管理", + "power" => "電源", + "update" => "更新", + "backup_restore" => "備份/恢復", + "factory_reset" => "恢復出廠設定", + "live_logs" => "日誌", + // Config page section headdings + "hardware_info" => "網關硬體信息", + "control_software" => "控制軟體", + "mmdvmhost_config" => "MMDVMHost 設定", + "general_config" => "常規設定", + "dmr_config" => "DMR 設定", + "dstar_config" => "D-Star 設定", + "ysf_config" => "Yaesu System Fusion 設定", + "p25_config" => "P25 設定", + "nxdn_config" => "NXDN 設定", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG 設定", + "mobilegps_config" => "Mobile GPS Configuration", + "fw_config" => "防火墻設定", + "remote_access_pw" => "遠程訪問密碼", + // Config Page - Section General + "setting" => "設定", + "value" => "設定值", + "apply" => "應用設定", + // Config Page - Gateway Hardware Information + "hostname" => "主機名", + "kernel" => "內核", + "platform" => "平臺", + "cpu_load" => "CPU 負荷", + "cpu_temp" => "CPU 溫度", + // Config Page - Control Software + "controller_software" => "控制器軟體", + "controller_mode" => "控制器模式", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR 模式", + "d-star_mode" => "D-Star 模式", + "ysf_mode" => "YSF 模式", + "p25_mode" => "P25 模式", + "nxdn_mode" => "NXDN 模式", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM 顯示器類型", + "mode_hangtime" => "模式停留時間", + // Config Page - General Configuration + "node_call" => "節點呼號", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "電臺頻率", + "lattitude" => "緯度", + "longitude" => "經度", + "town" => "區域", + "country" => "國家", + "url" => "URL", + "radio_type" => "電臺/調製解調器類型", + "node_type" => "節點類型", + "timezone" => "時區", + "dash_lang" => "儀錶盤語言", + // Config Page - DMR Configuration + "dmr_master" => "DMR 主機 (MMDVMHost)", + "bm_master" => "BrandMeister 主機 ", + "bm_network" => "BrandMeister 網絡", + "dmr_plus_master" => "DMR+ 主機 ", + "dmr_plus_network" => "DMR+ 網絡", + "xlx_master" => "XLX 主機 ", + "xlx_enable" => "XLX 主機啟用", + "dmr_cc" => "DMR 彩色碼", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 呼號", + "dstar_rpt2" => "RPT2 呼號", + "dstar_irc_password" => "ircDDBGateway 密碼", + "dstar_default_ref" => "默認反射器", + "aprs_host" => "APRS 服務器", + "dstar_irc_lang" => "ircDDBGateway 語言", + "dstar_irc_time" => "時間通告", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF 默認服務器", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 默認服務器", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN 默認服務器", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "儀表盤訪問", + "fw_irc" => "ircDDBGateway 遠程", + "fw_ssh" => "SSH訪問", + // Config Page - Password + "user" => "用戶名", + "password" => "密碼", + "set_password" => "密碼設定", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "啟用的模式", + "net_status" => "網絡狀態", + "internet" => "互聯網", + "radio_info" => "電臺信息", + "dstar_repeater" => "D-Star 中繼", + "dstar_net" => "D-Star 網絡", + "dmr_repeater" => "DMR 中繼", + "dmr_master" => "DMR 主機", + "ysf_net" => "YSF 網絡", + "p25_radio" => "P25 電臺", + "p25_net" => "P25 網絡", + "nxdn_radio" => "NXDN 電臺", + "nxdn_net" => "NXDN 網絡", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "時間", + "mode" => "模式", + "callsign" => "呼號", + "target" => "目標", + "src" => "源", // Short version of "Source" + "dur" => "時長", // Short version of "Duration" + "loss" => "丟失", + "ber" => "誤碼率", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "組", + "logoff" => "註銷", + "info" => "信息", + "utot" => "用户超時", // Short for User Timeout + "gtot" => "組超時", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "網關上最後 20 個呼叫", + "local_tx_list" => "最後 20 個本地呼叫", + "active_starnet_groups" => "激活 Starnet 組", + "active_starnet_members" => "激活 Starnet 組成員", + "d-star_link_manager" => "D-Star 連接管理器", + "d-star_link_status" => "D-Star 連接信息", + "service_status" => "服務狀態" +); +?> diff --git a/admin/lang/chinese_tw.php b/admin/lang/chinese_tw.php new file mode 100644 index 0000000..e7a6895 --- /dev/null +++ b/admin/lang/chinese_tw.php @@ -0,0 +1,155 @@ + "數位語音", + "configuration" => "組態設定", + "dashboard_for" => "控制台 -", + // Banner links + "dashboard" => "控制台", + "admin" => "管理", + "power" => "電源", + "update" => "更新", + "backup_restore" => "備份/還原", + "factory_reset" => "恢復出廠設定", + "live_logs" => "日誌", + // Config page section headdings + "hardware_info" => "硬體資訊", + "control_software" => "控制軟體", + "mmdvmhost_config" => "MMDVMHost 設定", + "general_config" => "一般設定", + "dmr_config" => "DMR 設定", + "dstar_config" => "D-Star 設定", + "ysf_config" => "Yaesu System Fusion 設定", + "p25_config" => "P25 設定", + "nxdn_config" => "NXDN 設定", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG 設定", + "mobilegps_config" => "Mobile GPS Configuration", + "fw_config" => "防火牆設定", + "remote_access_pw" => "遠端遙控密碼", + // Config Page - Section General + "setting" => "設定", + "value" => "設定值", + "apply" => "變更設定", + // Config Page - Gateway Hardware Information + "hostname" => "主機名稱", + "kernel" => "核心", + "platform" => "平台", + "cpu_load" => "CPU 負載", + "cpu_temp" => "CPU 溫度", + // Config Page - Control Software + "controller_software" => "控制器軟體", + "controller_mode" => "控制器模式", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR 模式", + "d-star_mode" => "D-Star 模式", + "ysf_mode" => "YSF 模式", + "p25_mode" => "P25 模式", + "nxdn_mode" => "NXDN 模式", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM 螢幕類型", + "mode_hangtime" => "模式保持時間", + // Config Page - General Configuration + "node_call" => "節點呼號", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "電台頻率", + "lattitude" => "緯度", + "longitude" => "經度", + "town" => "城市", + "country" => "國家", + "url" => "URL", + "radio_type" => "Modem 類型", + "node_type" => "節點類型", + "timezone" => "時區", + "dash_lang" => "介面語言", + // Config Page - DMR Configuration + "dmr_master" => "DMR 伺服器 (MMDVMHost)", + "bm_master" => "BrandMeister 伺服器", + "bm_network" => "BrandMeister 網路", + "dmr_plus_master" => "DMR+ 伺服器", + "dmr_plus_network" => "DMR+ 網路", + "xlx_master" => "XLX 伺服器", + "xlx_enable" => "啟用 XLX 伺服器", + "dmr_cc" => "DMR 色碼", + "dmr_embeddedlconly" => "僅允許指定 ID 連接", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 呼號", + "dstar_rpt2" => "RPT2 呼號", + "dstar_irc_password" => "ircDDBGateway 密碼", + "dstar_default_ref" => "預設反射器", + "aprs_host" => "APRS 伺服器", + "dstar_irc_lang" => "ircDDBGateway 語言", + "dstar_irc_time" => "時間提示", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF 預設伺服器", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 預設伺服器", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN 預設伺服器", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "控制台存取", + "fw_irc" => "ircDDBGateway 遠端遙控", + "fw_ssh" => "SSH 存取", + // Config Page - Password + "user" => "用戶名", + "password" => "密碼", + "set_password" => "密碼設定", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "已啟用模式", + "net_status" => "網路狀態", + "internet" => "網際網路", + "radio_info" => "RF 電台資訊", + "dstar_repeater" => "D-Star 中繼", + "dstar_net" => "D-Star 網路", + "dmr_repeater" => "DMR 中繼", + "dmr_master" => "DMR 伺服器", + "ysf_net" => "YSF 網路", + "p25_radio" => "P25 電台", + "p25_net" => "P25 網路", + "nxdn_radio" => "NXDN 電台", + "nxdn_net" => "NXDN 網路", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "時間", + "mode" => "模式", + "callsign" => "呼號", + "target" => "目標", + "src" => "來源", // Short version of "Source" + "dur" => "歷時", // Short version of "Duration" + "loss" => "丟失率", + "ber" => "誤碼率", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "群組", + "logoff" => "登出", + "info" => "資訊", + "utot" => "用户逾時", // Short for User Timeout + "gtot" => "群組逾時", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "最近 20 個通訊", + "local_tx_list" => "最近 20 個本地 RF 通訊", + "active_starnet_groups" => "啟用 Starnet 群組", + "active_starnet_members" => "啟用 Starnet 成員", + "d-star_link_manager" => "D-Star 連線管理", + "d-star_link_status" => "D-Star 連線狀態", + "service_status" => "服務狀態" +); +?> diff --git a/admin/lang/dutch_nl.php b/admin/lang/dutch_nl.php new file mode 100644 index 0000000..ed17370 --- /dev/null +++ b/admin/lang/dutch_nl.php @@ -0,0 +1,156 @@ + "Digital Voice", + "configuration" => "Configuratie", + "dashboard_for" => "Dashboard voor", + // Banner links + "dashboard" => "Dashboard", + "admin" => "Admin", + "power" => "Power", + "update" => "Update", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Reset all", + "live_logs" => "Actuele Logs", + // Config page section headdings + "hardware_info" => "Gateway hardware informatie", + "control_software" => "Controller Host software", + "mmdvmhost_config" => "MMDVMHost configuratie", + "general_config" => "Algemene configuratie", + "dmr_config" => "DMR configuratie", + "dstar_config" => "D-Star configuratie", + "ysf_config" => "Yaesu System Fusion configuratie", + "p25_config" => "P25 configuratie", + "nxdn_config" => "NXDN configuratie", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG configuratie", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wireless configuratie", + "fw_config" => "Firewall configuratie", + "remote_access_pw" => "Remote Access paswoord", + // Config Page - Section General + "setting" => "Instelling", + "value" => "Waarde", + "apply" => "Toepassen", + // Config Page - Gateway Hardware Information + "hostname" => "Hostnaam", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller software", + "controller_mode" => "Controller modus", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR modus", + "d-star_mode" => "D-Star modus", + "ysf_mode" => "YSF modus", + "p25_mode" => "P25 modus", + "nxdn_mode" => "NXDN modus", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM display type", + "mode_hangtime" => "Mode hangtijd", + // Config Page - General Configuration + "node_call" => "Node roepletters", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio frequentie", + "lattitude" => "Breedtegraad", + "longitude" => "Lengtegraad", + "town" => "Plaats", + "country" => "Land", + "url" => "URL", + "radio_type" => "Radio/Modem type", + "node_type" => "Node type", + "timezone" => "Systeem tijdzone", + "dash_lang" => "Dashboard taal", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister netwerk", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ netwerk", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master AAN", + "dmr_cc" => "DMR kleur code (CC)", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 roepletters", + "dstar_rpt2" => "RPT2 roepletters", + "dstar_irc_password" => "ircDDBGateway paswoord", + "dstar_default_ref" => "Standaard reflector", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway taal", + "dstar_irc_time" => "Tijd uitzenden", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF standaard Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 standaard Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN standaard Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Dashboard toegang", + "fw_irc" => "ircDDBGateway op afstand", + "fw_ssh" => "SSH toegang", + // Config Page - Password + "user" => "Gebruikersnaam", + "password" => "Paswoord", + "set_password" => "Voer paswoord in", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Actieve modi", + "net_status" => "Netwerk status", + "internet" => "Internet", + "radio_info" => "Radio info", + "dstar_repeater" => "D-Star repeater", + "dstar_net" => "D-Star netwerk", + "dmr_repeater" => "DMR repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF netwerk", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 netwerk", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN netwerk", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Tijd", + "mode" => "Mode", + "callsign" => "Roepletters", + "target" => "Doel", + "src" => "Bron", // Short version of "Source" + "dur" => "Duur", // Short version of "Duration" + "loss" => "Verlies", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Groep", + "logoff" => "Uitloggen", + "info" => "Informatie", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Laatste 20 oproepen gehoord (RX) via deze Gateway", + "local_tx_list" => "Laatste 20 oproepen verzonden (TX) via deze Gateway", + "active_starnet_groups" => "Actieve Starnet groepen", + "active_starnet_members" => "Actieve Starnet groepsleden", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Informatie", + "service_status" => "Service Status" +); +?> diff --git a/admin/lang/english_uk.php b/admin/lang/english_uk.php new file mode 100644 index 0000000..fc2d818 --- /dev/null +++ b/admin/lang/english_uk.php @@ -0,0 +1,157 @@ + "Digital Voice", + "configuration" => "Configuration", + "dashboard_for" => "Dashboard for", + // Banner links + "dashboard" => "Dashboard", + "admin" => "Admin", + "power" => "Power", + "update" => "Update", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Factory Reset", + "live_logs" => "Live Logs", + // Config page section headdings + "hardware_info" => "Gateway Hardware Information", + "control_software" => "Control Software", + "mmdvmhost_config" => "MMDVMHost Configuration", + "general_config" => "General Configuration", + "dmr_config" => "DMR Configuration", + "dstar_config" => "D-Star Configuration", + "ysf_config" => "Yaesu System Fusion Configuration", + "p25_config" => "P25 Configuration", + "nxdn_config" => "NXDN Configuration", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Configuration", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wireless Configuration", + "fw_config" => "Firewall Configuration", + "remote_access_pw" => "Remote Access Password", + // Config Page - Section General + "setting" => "Setting", + "value" => "Value", + "apply" => "Apply Changes", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller Software", + "controller_mode" => "Controller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Display Type", + "mode_hangtime" => "Mode Hangtime", + // Config Page - General Configuration + "node_call" => "Node Callsign", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frequency", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Town", + "country" => "Country", + "url" => "URL", + "radio_type" => "Radio/Modem Type", + "node_type" => "Node Type", + "timezone" => "System Time Zone", + "dash_lang" => "Dashboard Language", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Colour Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Callsign", + "dstar_rpt2" => "RPT2 Callsign", + "dstar_irc_password" => "Remote Password", + "dstar_default_ref" => "Default Reflector", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Language", + "dstar_irc_time" => "Time Announcements", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startup Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startup Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startup Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Dashboard Access", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH Access", + // Config Page - Password + "user" => "User Name", + "password" => "Password", + "set_password" => "Set Password", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes Enabled", + "net_status" => "Network Status", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Network", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Network", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Network", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Network", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Time", + "mode" => "Mode", + "callsign" => "Callsign", + "target" => "Target", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Group", + "logoff" => "LogOff", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Gateway Activity", + "local_tx_list" => "Local RF Activity", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Information", + "service_status" => "Service Status" +); +?> diff --git a/admin/lang/english_us.php b/admin/lang/english_us.php new file mode 100644 index 0000000..9a9610f --- /dev/null +++ b/admin/lang/english_us.php @@ -0,0 +1,157 @@ + "Digital Voice", + "configuration" => "Configuration", + "dashboard_for" => "Dashboard for", + // Banner links + "dashboard" => "Dashboard", + "admin" => "Admin", + "power" => "Power", + "update" => "Update", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Factory Reset", + "live_logs" => "Live Logs", + // Config page section headdings + "hardware_info" => "Gateway Hardware Information", + "control_software" => "Control Software", + "mmdvmhost_config" => "MMDVMHost Configuration", + "general_config" => "General Configuration", + "dmr_config" => "DMR Configuration", + "dstar_config" => "D-Star Configuration", + "ysf_config" => "Yaesu System Fusion Configuration", + "p25_config" => "P25 Configuration", + "nxdn_config" => "NXDN Configuration", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Configuration", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wireless Configuration", + "fw_config" => "Firewall Configuration", + "remote_access_pw" => "Remote Access Password", + // Config Page - Section General + "setting" => "Setting", + "value" => "Value", + "apply" => "Apply Changes", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller Software", + "controller_mode" => "Controller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Display Type", + "mode_hangtime" => "Mode Hangtime", + // Config Page - General Configuration + "node_call" => "Node Callsign", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frequency", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Town", + "country" => "Country", + "url" => "URL", + "radio_type" => "Radio/Modem Type", + "node_type" => "Node Type", + "timezone" => "System Time Zone", + "dash_lang" => "Dashboard Language", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Color Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Callsign", + "dstar_rpt2" => "RPT2 Callsign", + "dstar_irc_password" => "Remote Password", + "dstar_default_ref" => "Default Reflector", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Language", + "dstar_irc_time" => "Time Announcements", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startup Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startup Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startup Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Dashboard Access", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH Access", + // Config Page - Password + "user" => "User Name", + "password" => "Password", + "set_password" => "Set Password", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes Enabled", + "net_status" => "Network Status", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Network", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Network", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Network", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Network", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Time", + "mode" => "Mode", + "callsign" => "Callsign", + "target" => "Target", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Group", + "logoff" => "LogOff", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Gateway Activity", + "local_tx_list" => "Local RF Activity", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Information", + "service_status" => "Service Status" +); +?> diff --git a/admin/lang/french_fr.php b/admin/lang/french_fr.php new file mode 100644 index 0000000..6af05fb --- /dev/null +++ b/admin/lang/french_fr.php @@ -0,0 +1,157 @@ + "Relais numérique", + "configuration" => "Configuration", + "dashboard_for" => "Console pour", + // Banner links + "dashboard" => "Console", + "admin" => "Administration", + "power" => "Arrêt/Redémarrage", + "update" => "Mise à jour", + "backup_restore" => "Sauvegarde/Restauration", + "factory_reset" => "Réinitialisation Usine", + "live_logs" => "Surveillance des Logs", + // Config page section headdings + "hardware_info" => "Informations matérielles de la passerelle", + "control_software" => "Contrôle logiciel", + "mmdvmhost_config" => "Configuration de MMDVMHost", + "general_config" => "Configuration générale", + "dmr_config" => "Configuration DMR", + "dstar_config" => "Configuration D-STAR", + "ysf_config" => "Configuration Yaesu System Fusion", + "p25_config" => "Configuration P25", + "nxdn_config" => "Configuration NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuration POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuration Réseau WIFI", + "fw_config" => "Configuration du Firewall", + "remote_access_pw" => "Mot de passe accès distant", + // Config Page - Section General + "setting" => "Paramètres", + "value" => "Valeur", + "apply" => "Appliquer les modifications", + // Config Page - Gateway Hardware Information + "hostname" => "Nom d'hôte", + "kernel" => "Kernel", + "platform" => "Plateforme", + "cpu_load" => "Charge CPU", + "cpu_temp" => "Température CPU", + // Config Page - Control Software + "controller_software" => "Logiciel controleur", + "controller_mode" => "Mode controleur", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Mode DMR", + "d-star_mode" => "Mode D-Star", + "ysf_mode" => "Mode YSF", + "p25_mode" => "Mode P25", + "nxdn_mode" => "Mode NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Afficheur MMDVM", + "mode_hangtime" => "Mode Hangtime", + // Config Page - General Configuration + "node_call" => "Indicatif du Node", + "dmr_id" => "Id CCS7/DMR", + "radio_freq" => "Fréquence radio", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Ville", + "country" => "Pays", + "url" => "URL", + "radio_type" => "Modèle Radio/Modem", + "node_type" => "Type de Node", + "timezone" => "Fuseau horaire", + "dash_lang" => "Langage de la console", + // Config Page - DMR Configuration + "dmr_master" => "Master DMR(MMDVMHost)", + "bm_master" => "Master BrandMeister", + "bm_network" => "Réseau BrandMeister", + "dmr_plus_master" => "Master DMR+", + "dmr_plus_network" => "Réseau DMR+", + "xlx_master" => "Master XLX", + "xlx_enable" => "Master XLX actif", + "dmr_cc" => "Code Couleur DMR", + "dmr_embeddedlconly" => "DMR LC intégré uniquement", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Indicatif RPT1", + "dstar_rpt2" => "Indicatif RPT2", + "dstar_irc_password" => "Mot de passe ircDDBGateway", + "dstar_default_ref" => "Reflecteur par défaut", + "aprs_host" => "Hôte APRS", + "dstar_irc_lang" => "Langage ircDDBGateway", + "dstar_irc_time" => "Annonces horaires", + // Config Page - YSF Configuration + "ysf_startup_host" => "Room YSF au démarrage", + // Config Page - P25 Configuration + "p25_startup_host" => "Hôte de démarrage P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Hôte de démarrage NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Accès Console", + "fw_irc" => "Commande à distance ircDDBGateway", + "fw_ssh" => "Accès SSH", + // Config Page - Password + "user" => "Nom d'utilisateur", + "password" => "Mot de passe", + "set_password" => "Définir le mot de passe", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes actifs", + "net_status" => "État du réseau", + "internet" => "Internet", + "radio_info" => "Info Radio", + "dstar_repeater" => "Relais D-Star", + "dstar_net" => "Réseau D-Star", + "dmr_repeater" => "Relais DMR", + "dmr_master" => "Master DMR", + "ysf_net" => "Réseau YSF", + "p25_radio" => "Radio P25", + "p25_net" => "Réseau P25", + "nxdn_radio" => "Radio NXDN", + "nxdn_net" => "Réseau NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Heure", + "mode" => "Mode", + "callsign" => "Indicatif ", + "target" => "Cible", + "src" => "Source ", // Short version of "Source" + "dur" => "Durée ", // Short version of "Duration" + "loss" => "Pertes", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Groupe", + "logoff" => "Déconnexion", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Activité de la passerelle", + "local_tx_list" => "Activité locale de la voie radio", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "Administrateur du lien D-Star", + "d-star_link_status" => "Informations du lien D-Star", + "service_status" => "État du service" +); +?> diff --git a/admin/lang/german_de.php b/admin/lang/german_de.php new file mode 100644 index 0000000..1c2de46 --- /dev/null +++ b/admin/lang/german_de.php @@ -0,0 +1,157 @@ + "Digital Voice", + "configuration" => "Konfiguration", + "dashboard_for" => "Tableau für", + // Banner links + "dashboard" => "Tableau", + "admin" => "Admin", + "power" => "Strom", + "update" => "Aktualisieren", + "backup_restore" => "Datensicherung/Wiederherstellung", + "factory_reset" => "Werkseinstellung", + "live_logs" => "Protokoll", + // Config page section headdings + "hardware_info" => "Gateway Hardware Information", + "control_software" => "Kontrollsoftware", + "mmdvmhost_config" => "MMDVMHost Konfiguration", + "general_config" => "Basis Konfiguration", + "dmr_config" => "DMR Konfiguration", + "dstar_config" => "D-Star Konfiguration", + "ysf_config" => "Yaesu System Fusion Konfiguration", + "p25_config" => "P25 Konfiguration", + "nxdn_config" => "NXDN Konfiguration", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Konfiguration", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wlan Konfiguration", + "fw_config" => "Firewall Konfiguration", + "remote_access_pw" => "Fernzugriff", + // Config Page - Section General + "setting" => "Einstellung", + "value" => "Wert", + "apply" => "Speichern", + // Config Page - Gateway Hardware Information + "hostname" => "Rechnername", + "kernel" => "Kernel", + "platform" => "Plattform", + "cpu_load" => "CPU Last", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Kontroller Software", + "controller_mode" => "Kontroller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Modus", + "d-star_mode" => "D-Star Modus", + "ysf_mode" => "YSF Modus", + "p25_mode" => "P25 Modus", + "nxdn_mode" => "NXDN Modus", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Display Typ", + "mode_hangtime" => "Mode Nachlaufzeit", + // Config Page - General Configuration + "node_call" => "Node Rufzeichen", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frequenz", + "lattitude" => "Breitengrad", + "longitude" => "Längengrad", + "town" => "Stadt", + "country" => "Land", + "url" => "URL", + "radio_type" => "Radio/Modem Typ", + "node_type" => "Node Typ", + "timezone" => "Systemzeit Zone", + "dash_lang" => "Tableau Sprache", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Netzwerk", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Netzwerk", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Aktiv", + "dmr_cc" => "DMR Color Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Rufzeichen", + "dstar_rpt2" => "RPT2 Rufzeichen", + "dstar_irc_password" => "ircDDBGateway Passwort", + "dstar_default_ref" => "Standard Reflektor", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Sprache", + "dstar_irc_time" => "Zeit Ansagen", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startup Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startup Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startup Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Tableau Zugriff", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH Zugriff", + // Config Page - Password + "user" => "Benutzername", + "password" => "Passwort", + "set_password" => "Passwort setzen", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Aktive Modi", + "net_status" => "Netzwerk Status", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Relais", + "dstar_net" => "D-Star Netzwerk", + "dmr_repeater" => "DMR Relais", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Netzwerk", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Netzwerk", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Netzwerk", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Zeit", + "mode" => "Mode", + "callsign" => "Rufzeichen", + "target" => "Ziel", + "src" => "Quelle", // Short version of "Source" + "dur" => "Dauer", // Short version of "Duration" + "loss" => "Verlust", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Gruppe", + "logoff" => "LogOff", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Letzten 20 Rufzeichen, die gehört wurden", + "local_tx_list" => "Letzten 20 Rufzeichen, die dieses Gateway nutzten", + "active_starnet_groups" => "Aktive Starnet Gruppen", + "active_starnet_members" => "Aktive Starnet Gruppen Mitglieder", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Information", + "service_status" => "Service Status" + ); +?> diff --git a/admin/lang/greek_gr.php b/admin/lang/greek_gr.php new file mode 100644 index 0000000..02bb182 --- /dev/null +++ b/admin/lang/greek_gr.php @@ -0,0 +1,157 @@ + "Ψηφιακή Τηλεφωνία", + "configuration" => "Ρυθμίσεις", + "dashboard_for" => "Πίνακας Ελέγχου για τον", + // Banner links + "dashboard" => "Πίνακας Ελέγχου", + "admin" => "Διαχείριση", + "power" => "Απενεργοποίηση", + "update" => "Ενημέρωση", + "backup_restore" => "Εφεδρικό Αντίγραφο/Επαναφορά", + "factory_reset" => "Εργοστασιακές Ρυθμίσεις", + "live_logs" => "Αρχείο Καταγραφής", + // Config page section headdings + "hardware_info" => "Πληροφορίες Υλικού Πύλης", + "control_software" => "Πρόγραμμα Ελέγχου", + "mmdvmhost_config" => "Ρυθμίσεις του MMDVMHost", + "general_config" => "Γενικές Ρυθμίσεις", + "dmr_config" => "Ρυθμίσεις DMR", + "dstar_config" => "Ρυθμίσεις D-Star", + "ysf_config" => "Ρυθμίσεις Fusion", + "p25_config" => "Ρυθμίσεις P25", + "nxdn_config" => "Ρυθμίσεις NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Ρυθμίσεις POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Ρυθμίσεις WiFi", + "fw_config" => "Ρυθμίσεις Τείχους Προστασίας", + "remote_access_pw" => "Κωδικός Πρόσβασης", + // Config Page - Section General + "setting" => "Ρυθμίσεις", + "value" => "Τιμή", + "apply" => "Εφαρμογή", + // Config Page - Gateway Hardware Information + "hostname" => "Ονομα Συσκευής", + "kernel" => "Πυρήνας", + "platform" => "Πλατφόρμα", + "cpu_load" => "Φόρτος CPU", + "cpu_temp" => "Θερμοκρασία CPU", + // Config Page - Control Software + "controller_software" => "Πρόγραμμα Ελεγκτή", + "controller_mode" => "Κατάσταση Ελεγκτή", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Λειτουργία DMR", + "d-star_mode" => "Λειτουργία D-Star", + "ysf_mode" => "Λειτουργία YSF", + "p25_mode" => "Λειτουργία P25", + "nxdn_mode" => "Λειτουργία NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Τύπος Οθόνης MMDVM", + "mode_hangtime" => "Χρόνος Επαναφοράς Σάρωσης", + // Config Page - General Configuration + "node_call" => "Διακριτικό Κόμβου", + "dmr_id" => "Ταυτότητα CCS7/DMR", + "radio_freq" => "Συχνότητα", + "lattitude" => "Γεωγραφικό Πλάτος", + "longitude" => "Γεωγραφικό Μήκος", + "town" => "Πόλη", + "country" => "Χώρα", + "url" => "URL", + "radio_type" => "Τύπος Modem", + "node_type" => "Τύπος Κόμβου", + "timezone" => "Ζώνη Ωρας", + "dash_lang" => "Γλώσσα Πίνακα Ελέγχου", + // Config Page - DMR Configuration + "dmr_master" => "Εξυπηρετητής DMR (MMDVMHost)", + "bm_master" => "Εξυπηρετητής BrandMeister", + "bm_network" => "Δίκτυο BrandMeister", + "dmr_plus_master" => "Εξυπηρετητής DMR+", + "dmr_plus_network" => "Δίκτυο DMR+", + "xlx_master" => "Εξυπηρετητής XLX", + "xlx_enable" => "Ενεργοποίηση Εξυπηρετητή XLX", + "dmr_cc" => "Κωδικός Χρώματος DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Διακριτικό RPT1", + "dstar_rpt2" => "Διακριτικό RPT2", + "dstar_irc_password" => "Κωδικός ircDDBGateway", + "dstar_default_ref" => "Reflector Προεπιλογής", + "aprs_host" => "Κεντρικός Υπολ. APRS", + "dstar_irc_lang" => "Γλώσσα ircDDBGateway", + "dstar_irc_time" => "Αναγγελίες Ωρας", + // Config Page - YSF Configuration + "ysf_startup_host" => "Εξυπηρετητής Εκκίνησης YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Εξυπηρετητής Εκκίνησης P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Εξυπηρετητής Εκκίνησης NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Πρόσβαση στον Πίνακα Ελέγχου", + "fw_irc" => "Απομακρυσμένος ircDDBGateway", + "fw_ssh" => "Πρόσβαση SSH", + // Config Page - Password + "user" => "Ονομα Χρήστη", + "password" => "Κωδικός Πρόσβασης", + "set_password" => "Αλλαγή Κωδικού Πρόσβασης", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Ενεργές Λειτουργίες", + "net_status" => "Κατάσταση Δικτύου", + "internet" => "Διαδίκτυο", + "radio_info" => "Πληροφ. Ασυρμάτου", + "dstar_repeater" => "Αναμεταδότης D-Star", + "dstar_net" => "Δίκτυο D-Star", + "dmr_repeater" => "Αναμεταδότης DMR", + "dmr_master" => "Εξυπηρετητής DMR", + "ysf_net" => "Δίκτυο YSF", + "p25_radio" => "Ασύρματος P25", + "p25_net" => "Δίκτυο P25", + "nxdn_radio" => "Ασύρματος NXDN", + "nxdn_net" => "Δίκτυο NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Ωρα", + "mode" => "Λειτουργία", + "callsign" => "Διακριτικό", + "target" => "Προορισμός", + "src" => "Πηγή", // Short version of "Source" + "dur" => "Διάρκεια", // Short version of "Duration" + "loss" => "Απώλεια", + "ber" => "Σφάλματα", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Ομάδα", + "logoff" => "Αποσύνδεση", + "info" => "Πληροφορίες", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Τελευταία 20 διακριτικά που ακούστηκαν μέσω αυτής της Πύλης", + "local_tx_list" => "Τελευταία 20 διακριτικά που είχαν πρόσβαση σε αυτή την Πύλη", + "active_starnet_groups" => "Ενεργές Ομάδες Starnet", + "active_starnet_members" => "Ενεργά Μέλη Ομάδων Starnet", + "d-star_link_manager" => "Διαχειριστής Ζεύζης D-Star", + "d-star_link_status" => "Πληροφορίες Ζεύξης D-Star", + "service_status" => "Κατάσταση Υπηρεσίας" +); +?> diff --git a/admin/lang/hungarian_hu.php b/admin/lang/hungarian_hu.php new file mode 100644 index 0000000..5cb8937 --- /dev/null +++ b/admin/lang/hungarian_hu.php @@ -0,0 +1,157 @@ + "Digitális", + "configuration" => "Konfiguráció", + "dashboard_for" => "Irányítópult", + // Banner links + "dashboard" => "Irányítópult", + "admin" => "Admin", + "power" => "Tápellátás", + "update" => "Frissítés", + "backup_restore" => "Mentés/Visszaállítás", + "factory_reset" => "Gyári beállítás", + "live_logs" => "Élő forgalom", + // Config page section headdings + "hardware_info" => "Hardver információ", + "control_software" => "Vezérlő szoftver", + "mmdvmhost_config" => "MMDVMHost konfiguráció", + "general_config" => "Általános konfiguráció", + "dmr_config" => "DMR konfiguráció", + "dstar_config" => "D-Star konfiguráció", + "ysf_config" => "Yaesu System Fusion konfiguráció", + "p25_config" => "P25 konfiguráció", + "nxdn_config" => "NXDN konfiguráció", + "m17_config" => "M17 konfiguráció", + "pocsag_config" => "POCSAG konfiguráció", + "mobilegps_config" => "Mobil GPS konfiguráció", + "wifi_config" => "Wi-fi konfiguráció", + "fw_config" => "Tűzfal konfiguráció", + "remote_access_pw" => "Távoli hozzáférés jelszó", + // Config Page - Section General + "setting" => "Beállítás", + "value" => "Érték", + "apply" => "Alkalmaz", + // Config Page - Gateway Hardware Information + "hostname" => "Kiszolgáló neve", + "kernel" => "Kernel", + "platform" => "Rendszer", + "cpu_load" => "CPU Terhelés", + "cpu_temp" => "CPU Hőmérséklet", + // Config Page - Control Software + "controller_software" => "Vezérlő Szoftver", + "controller_mode" => "Mód", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mód", + "d-star_mode" => "D-Star Mód", + "ysf_mode" => "YSF Mód", + "p25_mode" => "P25 Mód", + "nxdn_mode" => "NXDN Mód", + "m17_mode" => "M17 Mód", + "mmdvm_display" => "MMDVM kijelző típusa", + "mode_hangtime" => "Mód tartási ideje", + // Config Page - General Configuration + "node_call" => "Hívójel", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frekvencia", + "lattitude" => "Szélességi kör", + "longitude" => "Hosszúsági kör", + "town" => "Város", + "country" => "Ország", + "url" => "URL", + "radio_type" => "Rádió/Modem típusa", + "node_type" => "Hozzáférési pont típusa", + "timezone" => "Időzóna", + "dash_lang" => "Irányítópult nyelve", + // Config Page - DMR Configuration + "dmr_master" => "DMR Szerver (MMDVMHost)", + "bm_master" => "BrandMeister Szerver", + "bm_network" => "BrandMeister Hálózat", + "dmr_plus_master" => "DMR+ Szerver", + "dmr_plus_network" => "DMR+ Hálózat", + "xlx_master" => "XLX Szerver", + "xlx_enable" => "XLX Szerver engedélyezése", + "dmr_cc" => "DMR Color kód", + "dmr_embeddedlconly" => "DMR GPS/Talker Alias kikapcsolása", + "dmr_dumptadata" => "DMR GPS/Talker Alias mentése logba", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Hívójel", + "dstar_rpt2" => "RPT2 Hívójel", + "dstar_irc_password" => "Jelszó", + "dstar_default_ref" => "Alapértelmezett reflektor", + "aprs_host" => "APRS", + "dstar_irc_lang" => "ircDDBGateway Nyelv", + "dstar_irc_time" => "Idő hirdetmények", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF kiszolgáló", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 kiszolgáló", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN kiszolgáló", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 kiszolgáló", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "Mobil GPS", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Sebessége", + // Config Page - Firewall Configuration + "fw_dash" => "Irányítópult hozzáférés", + "fw_irc" => "ircDDBGateway távoli hozzáférés", + "fw_ssh" => "SSH hozzáférés", + // Config Page - Password + "user" => "Felhasználónév", + "password" => "Jelszó", + "set_password" => "Beállítás", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Bekapcsolt módok", + "net_status" => "Hálózat státusza", + "internet" => "Internet", + "radio_info" => "Rádió infó", + "dstar_repeater" => "D-Star átjátszó", + "dstar_net" => "D-Star hálózat", + "dmr_repeater" => "DMR átjátszó", + "dmr_master" => "DMR hálózat", + "ysf_net" => "YSF hálózat", + "p25_radio" => "P25 rádió", + "p25_net" => "P25 hálózat", + "nxdn_radio" => "NXDN rádió", + "nxdn_net" => "NXDN hálózat", + "m17_radio" => "M17 rádió", + "m17_net" => "M17 hálózat", + // Dashboard Front Page - Calls + "time" => "Idő", + "mode" => "Mód", + "callsign" => "Hívójel", + "target" => "Cél", + "src" => "Forrás", // Short version of "Source" + "dur" => "Hossz", // Short version of "Duration" + "loss" => "Veszteség", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET aktivitás", + "pocsag_timeslot" => "Időrés", + "pocsag_msg" => "Üzenet", + // Dashboard - Extra Info + "group" => "Csoport", + "logoff" => "LogOff", + "info" => "Információ", + "utot" => "FIT", // Short for User Timeout + "gtot" => "CSIT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Átjáró aktivitás", + "local_tx_list" => "Helyi RF aktivitás", + "active_starnet_groups" => "Aktív Starnet csoport", + "active_starnet_members" => "Aktív Starnet csoport résztvevők", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Információ", + "service_status" => "Szolgáltatás állapota" +); +?> diff --git a/admin/lang/index.php b/admin/lang/index.php new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/admin/lang/index.php @@ -0,0 +1 @@ + diff --git a/admin/lang/italian_it.php b/admin/lang/italian_it.php new file mode 100644 index 0000000..548b0e1 --- /dev/null +++ b/admin/lang/italian_it.php @@ -0,0 +1,157 @@ + "Modi Digitali", + "configuration" => "Configurazioni", + "dashboard_for" => "Cruscotto", + // Banner links + "dashboard" => "Cruscotto", + "admin" => "Admin", + "power" => "Power", + "update" => "Aggiornamento", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Ripristino", + "live_logs" => "Live Logs", + // Config page section headdings + "hardware_info" => "Informazioni Hardware del Gateway", + "control_software" => "Software di controllo", + "mmdvmhost_config" => "MMDVMHost Config", + "general_config" => "Configurazione Generale", + "dmr_config" => "DMR Config", + "dstar_config" => "D-Star Configuration", + "ysf_config" => "Yaesu System Fusion Config", + "p25_config" => "P25 Config", + "nxdn_config" => "NXDN Config", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Config", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wireless Config", + "fw_config" => "Firewall Config", + "remote_access_pw" => "Password Accesso Remoto", + // Config Page - Section General + "setting" => "Settaggi", + "value" => "Valori", + "apply" => "Applicare le modifiche", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller Software", + "controller_mode" => "Controller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Display Type", + "mode_hangtime" => "Tempo Ritardo", + // Config Page - General Configuration + "node_call" => "Nominativo", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frequenza Radio", + "lattitude" => "Latitudine", + "longitude" => "Longitudine", + "town" => "Città", + "country" => "Stato", + "url" => "URL", + "radio_type" => "Radio/Modem Modello", + "node_type" => "Tipo di Nodo", + "timezone" => "Fuso Orario", + "dash_lang" => "Linguaggio Cruscotto", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Attivo", + "dmr_cc" => "DMR Colour Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Nominativo RPT1", + "dstar_rpt2" => "Nominativo RPT2", + "dstar_irc_password" => "ircDDBGateway Password", + "dstar_default_ref" => "Default Reflector", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Linguaggio", + "dstar_irc_time" => "Annuncio (Vocale) Orario", + // Config Page - YSF Configuration + "ysf_startup_host" => "Room YSF Di Partenza", + // Config Page - P25 Configuration + "p25_startup_host" => "Room P25 Di Partenza", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Room NXDN Di Partenza", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Accesso Cruscotto", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "Accesso SSH", + // Config Page - Password + "user" => "Nome Utente", + "password" => "Password", + "set_password" => "Imposta Password", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modi Attivi", + "net_status" => "Stato Rete", + "internet" => "Internet", + "radio_info" => "Info Radio", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Network", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Network", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Network", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Network", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Ora", + "mode" => "Modo", + "callsign" => "Nominativo", + "target" => "Target", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Gruppo", + "logoff" => "LogOff", + "info" => "Informazioni", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Le Ultime 20 Trasmissioni Di Questo Nodo", + "local_tx_list" => "Gli Ultimi 20 Accessi RF Su Questo Nodo", + "active_starnet_groups" => "Gruppi Attivi Starnet", + "active_starnet_members" => "Menbri Attivi Nel Gruppo Starnet", + "d-star_link_manager" => "Gestione D-Star Link", + "d-star_link_status" => "Info D-Star Link", + "service_status" => "Stato Servizi" +); +?> diff --git a/admin/lang/japanese_jp.php b/admin/lang/japanese_jp.php new file mode 100644 index 0000000..ae6b068 --- /dev/null +++ b/admin/lang/japanese_jp.php @@ -0,0 +1,159 @@ + "デジタルボイス", + "configuration" => "設定", + "dashboard_for" => "ダッシュボード for", + // Banner links + "dashboard" => "ダッシュボード", + "admin" => "制御", + "power" => "電源", + "update" => "更新", + "backup_restore" => "バックアップ/復旧", + "factory_reset" => "工場出荷に戻る", + "live_logs" => "ログ", + // Config page section headdings + "hardware_info" => "ゲートウェイハード情報", + "control_software" => "制御ソフトウェア", + "mmdvmhost_config" => "MMDVMHost設定", + "general_config" => "全般設定", + "dmr_config" => "DMR設定", + "dstar_config" => "D-Star設定", + "ysf_config" => "YSF設定", + "p25_config" => "P25設定", + "nxdn_config" => "NXDN設定", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG設定", + "mobilegps_config" => "外部GPS設定", + "wifi_config" => "無線LAN設定", + "fw_config" => "ファイアウォール設定", + "remote_access_pw" => "遠隔ログインパスワード", + // Config Page - Section General + "setting" => "設定項目", + "value" => "設定内容", + "apply" => "更新", + // Config Page - Gateway Hardware Information + "hostname" => "ホスト名", + "kernel" => "カーネル", + "platform" => "マイコン", + "cpu_load" => "CPU負荷", + "cpu_temp" => "CPU温度", + // Config Page - Control Software + "controller_software" => "制御ソフト", + "controller_mode" => "制御モード", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMRモード", + "d-star_mode" => "D-Starモード", + "ysf_mode" => "YSFモード", + "p25_mode" => "P25モード", + "nxdn_mode" => "NXDNモード", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVMディスプレイタイプ", + "mode_hangtime" => "モード保持時間", + // Config Page - General Configuration + "node_call" => "ノード コールサイン", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "周波数", + "lattitude" => "緯度", + "longitude" => "経度", + "town" => "市町村", + "country" => "国", + "url" => "URL", + "radio_type" => "Radio/Modem タイプ", + "node_type" => "ノードタイプ", + "timezone" => "タイムゾーン", + "dash_lang" => "言語", + // Config Page - DMR Configuration + "dmr_master" => "DMRマスター(MMDVMHost)", + "bm_master" => "BrandMeisterマスター", + "bm_network" => "BrandMeisterネットワーク", + "dmr_plus_master" => "DMR+マスター", + "dmr_plus_network" => "DMR+ネットワーク", + "xlx_master" => "XLXマスター", + "xlx_enable" => "XLXマスター有効", + "dmr_cc" => "DMRカラーコード", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1コールサイン", + "dstar_rpt2" => "RPT2コールサイン", + "dstar_irc_password" => "ircDDBGatewayパスワード", + "dstar_default_ref" => "初期接続リフレクター", + "aprs_host" => "APRSホスト", + "dstar_irc_lang" => "ircDDBGateway言語", + "dstar_irc_time" => "時刻アナウンス", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF初期接続ホスト", + // Config Page - P25 Configuration + "p25_startup_host" => "P25初期接続ホスト", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN初期接続ホスト", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "外部GPS有効", + "mobilegps_port" => "GPSポート", + "mobilegps_speed" => "GPSポート速度", + // Config Page - Firewall Configuration + "fw_dash" => "ダッシュボードアクセス", + "fw_irc" => "ircDDBGatewayリモート", + "fw_ssh" => "SSHアクセス", + // Config Page - Password + "user" => "ユーザー名", + "password" => "パスワード", + "set_password" => "パスワード保存", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "使用可能モード", + "net_status" => "ネットワーク状況", + "internet" => "インターネット", + "radio_info" => "無線モデム情報", + "dstar_repeater" => "D-Starレピーター", + "dstar_net" => "D-Starネットワーク", + "dmr_repeater" => "DMRレピーター", + "dmr_master" => "DMRマスター", + "ysf_net" => "YSFネットワーク", + "p25_radio" => "P25 Radio", + "p25_net" => "P25ネットワーク", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDNネットワーク", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "時刻", + "mode" => "モード", + "callsign" => "コールサイン", + "target" => "ターゲット", + "src" => "ソース", // Short version of "Source" + "dur" => "時間", // Short version of "Duration" + "loss" => "ロス", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNETゲートウェイ状態", + "pocsag_timeslot" => "タイムスロット", + "pocsag_msg" => "メッセージ", + // Dashboard - Extra Info + "group" => "グループ", + "logoff" => "ログオフ", + "info" => "情報", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "受信リスト(最新20局)", + "local_tx_list" => "送信リスト(最新20局)", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "D-Star接続マネージャー", + "d-star_link_status" => "D-Star接続情報", + "service_status" => "サービス状態" +); +?> diff --git a/admin/lang/norwegian_no.php b/admin/lang/norwegian_no.php new file mode 100644 index 0000000..23f6983 --- /dev/null +++ b/admin/lang/norwegian_no.php @@ -0,0 +1,157 @@ + "Digital Voice", + "configuration" => "Konfigurasjon", + "dashboard_for" => "Skrivebord for", + // Banner links + "dashboard" => "Skrivebord", + "admin" => "Admin", + "power" => "Strøm", + "update" => "Oppdater", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Tilbakestill", + "live_logs" => "Live Logg", + // Config page section headdings + "hardware_info" => "Gateway Hardware Informasjon", + "control_software" => "Kontroller Programvare", + "mmdvmhost_config" => "MMDVMHost Konfigurasjon", + "general_config" => "Generel Konfigurasjon", + "dmr_config" => "DMR Konfigurasjon", + "dstar_config" => "D-Star Konfigurasjon", + "ysf_config" => "Yaesu System Fusion Konfigurasjon", + "p25_config" => "P25 Konfigurasjon", + "nxdn_config" => "NXDN Konfigurasjon", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Konfigurasjon", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Trådløs Konfigurasjon", + "fw_config" => "Firewall Konfigurasjon", + "remote_access_pw" => "Fjerntilgangs passord", + // Config Page - Section General + "setting" => "Innstillinger", + "value" => "Verdi", + "apply" => "Bruk endringer", + // Config Page - Gateway Hardware Information + "hostname" => "Vertsnavn", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU-belastning", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Kontroller Programvare", + "controller_mode" => "Kontroller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Skjerm Type", + "mode_hangtime" => "Mode Hangtime", + // Config Page - General Configuration + "node_call" => "Node Kallesignal", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frekvens", + "lattitude" => "Breddegrad", + "longitude" => "lengdegrad", + "town" => "By", + "country" => "Land", + "url" => "URL", + "radio_type" => "Radio/Modem Type", + "node_type" => "Node Type", + "timezone" => "Tidssone", + "dash_lang" => "Skrivebord Språk", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Nettverk", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Nettverk", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Aktivert", + "dmr_cc" => "DMR Farge Kode", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Kallesignal", + "dstar_rpt2" => "RPT2 Kallesignal", + "dstar_irc_password" => "ircDDBGateway Passord", + "dstar_default_ref" => "Standard Reflektor", + "aprs_host" => "APRS Vert", + "dstar_irc_lang" => "ircDDBGateway Språk", + "dstar_irc_time" => "Tids annonsering", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Oppstarts Vert", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Oppstarts Vert", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Oppstarts Vert", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Skrivebord Adgang", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH Adgang", + // Config Page - Password + "user" => "Bruker navn", + "password" => "Passord", + "set_password" => "Set Passord", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes Aktivert", + "net_status" => "Nettverk Status", + "internet" => "Internett", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Nettverk", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Nettverk", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Nettverk", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Nettverk", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Tid", + "mode" => "Mode", + "callsign" => "Kallesignal", + "target" => "Destinasjon", + "src" => "Src", // Short version of "Source" + "dur" => "Var", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Gruppe", + "logoff" => "Logg Av", + "info" => "Informasjon", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "De siste 20 anropene hørt via denne Gatewayen", + "local_tx_list" => "De siste 20 anropene som åpnet denne Gatewayen", + "active_starnet_groups" => "Aktive Starnet Grupper", + "active_starnet_members" => "Aktive Starnet Gruppe medlemer", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Informasjon", + "service_status" => "Service Status" +); +?> diff --git a/admin/lang/polish_pl.php b/admin/lang/polish_pl.php new file mode 100644 index 0000000..1670385 --- /dev/null +++ b/admin/lang/polish_pl.php @@ -0,0 +1,157 @@ + "Tryb cyfrowy", + "configuration" => "Konfiguracja", + "dashboard_for" => "Panel użytkownika", + // Banner links + "dashboard" => "Panel", + "admin" => "Zarządzanie", + "power" => "Zasilanie", + "update" => "Aktualizacja", + "backup_restore" => "Kopia/Przywracanie", + "factory_reset" => "Resetowanie", + "live_logs" => "Logi na żywo", + // Config page section headdings + "hardware_info" => "Informacje sprzętowe bramki", + "control_software" => "Oprogramowanie sterujące", + "mmdvmhost_config" => "Konfiguracja MMDVMHost", + "general_config" => "Konfiguracja główna", + "dmr_config" => "Konfiguracja DMR", + "dstar_config" => "Konfiguracja D-Star", + "ysf_config" => "Konfiguracja Yaesu System Fusion", + "p25_config" => "Konfiguracja P25", + "nxdn_config" => "Konfiguracja NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Konfiguracja POCSAG", + "mobilegps_config" => "Konfiguracja przenośnego GPS", + "wifi_config" => "Konfiguracja WiFi", + "fw_config" => "Konfiguracja zapory sieciowej", + "remote_access_pw" => "Hasło dostępu zdalnego", + // Config Page - Section General + "setting" => "Ustawienie", + "value" => "Wartość", + "apply" => "Zatwierdź zmiany", + // Config Page - Gateway Hardware Information + "hostname" => "Nazwa hosta", + "kernel" => "Kernel", + "platform" => "Platforma", + "cpu_load" => "Obciążenie CPU", + "cpu_temp" => "Temperatura CPU", + // Config Page - Control Software + "controller_software" => "Oprogramowanie kontrolera", + "controller_mode" => "Tryb kontrolera", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Tryb DMR", + "d-star_mode" => "Tryb D-Star", + "ysf_mode" => "Tryb YSF", + "p25_mode" => "Tryb P25", + "nxdn_mode" => "Tryb NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Typ wyświetlacza MMDVM", + "mode_hangtime" => "Tryb czasu oczekiwania", + // Config Page - General Configuration + "node_call" => "Znak krótkofalarski bramki", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Częstotliwość radia", + "lattitude" => "Szerokość geograficzna", + "longitude" => "Długość geograficzna", + "town" => "Miejscowość", + "country" => "Państwo", + "url" => "URL", + "radio_type" => "Typ radia/modemu", + "node_type" => "Rodzaj bramki", + "timezone" => "Strefa czasowa", + "dash_lang" => "Język panelu", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "Sieć BrandMeister", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "Sieć DMR+", + "xlx_master" => "XLX Master", + "xlx_enable" => "Włączony XLX Master", + "dmr_cc" => "DMR Colour Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Znak RPT1", + "dstar_rpt2" => "Znak RPT2", + "dstar_irc_password" => "Hasło dostępu zdalnego", + "dstar_default_ref" => "Domyślny reflektor", + "aprs_host" => "Host APRS", + "dstar_irc_lang" => "Język ircDDBGateway", + "dstar_irc_time" => "Czas zapowiedzi", + // Config Page - YSF Configuration + "ysf_startup_host" => "Startowy host YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Startowy host P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Startowy host NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "Włączanie przenośnego GPS", + "mobilegps_port" => "Port GPS", + "mobilegps_speed" => "Prędkość portu GPS", + // Config Page - Firewall Configuration + "fw_dash" => "Dostęp do panelu", + "fw_irc" => "Zdalny ircDDBGateway", + "fw_ssh" => "Dostęp SSH", + // Config Page - Password + "user" => "Nazwa użytkownika", + "password" => "Hasło", + "set_password" => "Ustaw hasło", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Włączone tryby", + "net_status" => "Status sieci", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "Przemiennik D-Star", + "dstar_net" => "Sieć D-Star", + "dmr_repeater" => "Przemiennik DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "Sieć YSF", + "p25_radio" => "Radio P25", + "p25_net" => "Sieć P25", + "nxdn_radio" => "Radio NXDN", + "nxdn_net" => "Sieć NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Czas", + "mode" => "Tryb", + "callsign" => "Znak", + "target" => "Cel", + "src" => "Źródło", + "dur" => "Okres", + "loss" => "Straty", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "Aktywność bramy DAPNET", + "pocsag_timeslot" => "Szczelina czasowa", + "pocsag_msg" => "Wiadomość", + // Dashboard - Extra Info + "group" => "Grupa", + "logoff" => "Wyloguj", + "info" => "Informacja", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Aktywność bramki", + "local_tx_list" => "Atywność radiowa lokalna", + "active_starnet_groups" => "Aktywne grupy Starnet", + "active_starnet_members" => "Aktywni członkowie grupy Starnet", + "d-star_link_manager" => "Zarządzanie linkami D-Star", + "d-star_link_status" => "Status linków D-Star", + "service_status" => "Status serwisu" +); +?> diff --git a/admin/lang/portuguese_br.php b/admin/lang/portuguese_br.php new file mode 100644 index 0000000..f7fe2ec --- /dev/null +++ b/admin/lang/portuguese_br.php @@ -0,0 +1,157 @@ + "Digital Voz", + "configuration" => "Configuração", + "dashboard_for" => "Painel de Controle de", + // Banner links + "dashboard" => "Painel", + "admin" => "Admin", + "power" => "Ação", + "update" => "Atualizar", + "backup_restore" => "Backup/Restaurar", + "factory_reset" => "Reset", + "live_logs" => "Logs online", + // Config page section headdings + "hardware_info" => "Informações Hardware do Gateway", + "control_software" => "Controle Software", + "mmdvmhost_config" => "MMDVMHost Configuração", + "general_config" => "Configurações Gerais", + "dmr_config" => "Configuração do DMR", + "dstar_config" => "Configuração do D-Star", + "ysf_config" => "Configuração do Sistema Yaesu Fusion", + "p25_config" => "Configuração do P25", + "nxdn_config" => "Configuração do NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuração do POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuração do Wireless", + "fw_config" => "Configuração do Firewall", + "remote_access_pw" => "Senha do Acesso Remoto", + // Config Page - Section General + "setting" => "Configurações", + "value" => "Valores", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Nome do Host", + "kernel" => "Kernel", + "platform" => "Plataforma", + "cpu_load" => "Leitura de CPU", + "cpu_temp" => "Temperatura de CPU", + // Config Page - Control Software + "controller_software" => "Tipo de Software", + "controller_mode" => "Modo de Controle", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Modo DMR", + "d-star_mode" => "Modo D-Star", + "ysf_mode" => "Modo YSF", + "p25_mode" => "Modo P25", + "nxdn_mode" => "Modo NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Exibição MMDVM", + "mode_hangtime" => "Modo Tempo de Espera", + // Config Page - General Configuration + "node_call" => "Indicativo do Node", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frequencia do Rádio", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Cidade", + "country" => "País", + "url" => "URL", + "radio_type" => "Tipo de Radio/Modem", + "node_type" => "Tipo de Node", + "timezone" => "Horário do Sistema", + "dash_lang" => "Idioma do Painel de Controle", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Rede", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "Código de Cores DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Indicativo", + "dstar_rpt2" => "RPT2 Indicativo", + "dstar_irc_password" => "Senha ircDDBGateway", + "dstar_default_ref" => "Refletor Principal", + "aprs_host" => "Servidor APRS", + "dstar_irc_lang" => "Idioma ircDDBGateway", + "dstar_irc_time" => "Anúncio a cada Hora", + // Config Page - YSF Configuration + "ysf_startup_host" => "Servidor Inicial YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Servidor Inicial P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Servidor Inicial NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Acesso ao Painel", + "fw_irc" => "Remoto ircDDBGateway", + "fw_ssh" => "Acesso via SSH", + // Config Page - Password + "user" => "Nome do Usuário", + "password" => "Senha", + "set_password" => "Modificar Senha", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Habilitar Modos", + "net_status" => "Status de Rede", + "internet" => "Internet", + "radio_info" => "Info do Rádio", + "dstar_repeater" => "Repetidora D-Star", + "dstar_net" => "Rede D-Star", + "dmr_repeater" => "Repetidora DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "Rede YSF", + "p25_radio" => "Rádio P25", + "p25_net" => "Rede P25", + "nxdn_radio" => "Rádio NDXN", + "nxdn_net" => "Rede NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Hora", + "mode" => "Modo", + "callsign" => "Indicativo", + "target" => "Alvo", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Grupo", + "logoff" => "Sair", + "info" => "Informação", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Últimas 20 chamadas via Gateway", + "local_tx_list" => "Últimas 20 chamadas por este Gateway", + "active_starnet_groups" => "Grupo Ativos na Starnet", + "active_starnet_members" => "Grupo de Membros Ativos na Starnet", + "d-star_link_manager" => "Gerenciar Conexão D-Star", + "d-star_link_status" => "Informações do Link D-Star", + "service_status" => "Status do Sistema" +); +?> diff --git a/admin/lang/portuguese_pt.php b/admin/lang/portuguese_pt.php new file mode 100644 index 0000000..15c1046 --- /dev/null +++ b/admin/lang/portuguese_pt.php @@ -0,0 +1,158 @@ + "Digital Voz", + "configuration" => "Configuração", + "dashboard_for" => "Painel de Controle de", + // Banner links + "dashboard" => "Painel", + "admin" => "Admin", + "power" => "Ação", + "update" => "Atualizar", + "backup_restore" => "Backup/Restauro", + "factory_reset" => "Reset", + "live_logs" => "Logs online", + // Config page section headdings + "hardware_info" => "Informações Hardware do Gateway", + "control_software" => "Controle Software", + "mmdvmhost_config" => "MMDVMHost Configuração", + "general_config" => "Configurações Gerais", + "dmr_config" => "Configuração do DMR", + "dstar_config" => "Configuração do DSTAR", + "ysf_config" => "Configuração do Yaesu System Fusion", + "p25_config" => "Configuração do P25", + "nxdn_config" => "Configuração do NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuração do POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuração do Wireless", + "fw_config" => "Configuração do Firewall", + "remote_access_pw" => "Senha do Acesso Remoto", + // Config Page - Section General + "setting" => "Configurações", + "value" => "Valores", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Nome do Host", + "kernel" => "Kernel", + "platform" => "Plataforma", + "cpu_load" => "Carga do CPU", + "cpu_temp" => "Temperatura do CPU", + // Config Page - Control Software + "controller_software" => "Tipo de Software", + "controller_mode" => "Modo de Controle", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Modo DMR", + "d-star_mode" => "Modo DSTAR", + "ysf_mode" => "Modo YSF", + "p25_mode" => "Modo P25", + "nxdn_mode" => "Modo NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Exibição MMDVM", + "mode_hangtime" => "Espera tempo do Modo", + // Config Page - General Configuration + "node_call" => "Indicativo do Nó", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frequência do Rádio", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Cidade", + "country" => "País", + "url" => "URL", + "radio_type" => "Tipo de Radio/Modem", + "node_type" => "Tipo de Nó", + "timezone" => "Horário do Sistema", + "dash_lang" => "Idioma do Painel de Controle", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "Rede BrandMeister", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "Rede DMR+", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "Código de Cores DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "R1 Indicativo", + "dstar_rpt2" => "R2 Indicativo", + "dstar_irc_password" => "Senha ircDDBGateway", + "dstar_default_ref" => "Refletor Principal", + "aprs_host" => "Servidor APRS", + "dstar_irc_lang" => "Idioma ircDDBGateway", + "dstar_irc_time" => "Anúncio a cada hora", + // Config Page - YSF Configuration + "ysf_startup_host" => "Servidor Inicial YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Servidor Inicial P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Servidor Inicial NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Acesso ao Painel", + "fw_irc" => "Remoto ircDDBGateway", + "fw_ssh" => "Acesso via SSH", + // Config Page - Password + "user" => "Nome utilizador", + "password" => "Senha", + "set_password" => "Modificar Senha", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Habilitar Modos", + "net_status" => "Estado da Rede", + "internet" => "Internet", + "radio_info" => "Info do Rádio", + "dstar_repeater" => "Repetidor DSTAR", + "dstar_net" => "Rede DSTAR", + "dmr_repeater" => "Repetidor DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "Rede YSF", + "p25_radio" => "Rádio P25", + "p25_net" => "Rede P25", + "nxdn_radio" => "Rádio NXDN", + "nxdn_net" => "Rede NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Hora", + "mode" => "Modo", + "callsign" => "Indicativo", // versão traduzida de "callsign" + "target" => "Alvo", // versão traduzida de "Target" + "src" => "Origem", // versão traduzida de "Source" + "dur" => "Dur.", // versão abreviada de "Duration" + "loss" => "Perda", + "ber" => "BER", // versão abreviada de "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Grupo", + "logoff" => "Sair", + "info" => "Informação", + "utot" => "UTOT", // abreviatura para Timeout do utilizador + "gtot" => "GTOT", // abreviatura para Timeout do grupo + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Últimas 20 chamadas através deste Gateway", + "local_tx_list" => "Últimas 20 chamadas deste Gateway", + "active_starnet_groups" => "Grupos ativos na Starnet", + "active_starnet_members" => "Grupo de membros ativos na Starnet", + "d-star_link_manager" => "Gerir a ligação DSTAR", + "d-star_link_status" => "Informações do Link DSTAR", + "service_status" => "Estado do Sistema" +); +?> + diff --git a/admin/lang/romanian_ro.php b/admin/lang/romanian_ro.php new file mode 100644 index 0000000..8af9f0a --- /dev/null +++ b/admin/lang/romanian_ro.php @@ -0,0 +1,157 @@ + "Voce Digitala", + "configuration" => "Configuratii", + "dashboard_for" => "Panou Control pentru", + // Banner links + "dashboard" => "Panou Control", + "admin" => "Administrator", + "power" => "Alimentare", + "update" => "Actualizare", + "backup_restore" => "Copie Rezerva/Restabilire", + "factory_reset" => "Resetare Stare Initiala", + "live_logs" => "Jurnal Live", + // Config page section headdings + "hardware_info" => "Informatii Hardware Gateway", + "control_software" => "Control Software", + "mmdvmhost_config" => "Configurare MMDVMHost", + "general_config" => "Configurari Generale", + "dmr_config" => "Configurari DMR", + "dstar_config" => "Configurari D-Star", + "ysf_config" => "Configurari Yaesu System Fusion", + "p25_config" => "Configurari P25", + "nxdn_config" => "Configurari NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configurari POCSAG", + "mobilegps_config" => "Configurari Mobile GPS", + "wifi_config" => "Configurari Retea Wireless", + "fw_config" => "Configurari Firewall", + "remote_access_pw" => "Parola Acces Exterior", + // Config Page - Section General + "setting" => "Setari", + "value" => "Valoare", + "apply" => "Salvare Setari", + // Config Page - Gateway Hardware Information + "hostname" => "Denumire Detinator", + "kernel" => "Nucleu", + "platform" => "Platforma", + "cpu_load" => "Incarcare CPU", + "cpu_temp" => "Temeratura CPU", + // Config Page - Control Software + "controller_software" => "Program de Control", + "controller_mode" => "Mod Control", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Mod DMR", + "d-star_mode" => "Mod D-Star", + "ysf_mode" => "Mod YSF", + "p25_mode" => "Mod P25", + "nxdn_mode" => "Mod NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Tip Display MMDVM", + "mode_hangtime" => "Control Hangtime", + // Config Page - General Configuration + "node_call" => "Indicativ Node", + "dmr_id" => "CCS7/ID DMR", + "radio_freq" => "Frecventa Radio", + "lattitude" => "Latitudine", + "longitude" => "Longitudine", + "town" => "Oras", + "country" => "Tara", + "url" => "URL", + "radio_type" => "Model Radio/Modem", + "node_type" => "Model Node", + "timezone" => "Time Zone Sistem", + "dash_lang" => "Limba Panou Control", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "Reteaua BrandMeister", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "Retea DMR+", + "xlx_master" => "XLX Master", + "xlx_enable" => "Activare XLX Master", + "dmr_cc" => "Cod Culoare DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Indicativ RPT1", + "dstar_rpt2" => "Indicativ RPT2", + "dstar_irc_password" => "parola ircDDBGateway", + "dstar_default_ref" => "Reflector Implicit ", + "aprs_host" => "Detinator APRS", + "dstar_irc_lang" => "Limba ircDDBGateway", + "dstar_irc_time" => "Timp instiintare", + // Config Page - YSF Configuration + "ysf_startup_host" => "lansare Detinator YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "lansare Detinator P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "lansare Detinator NXDN", + "nxdn_ran" => "Lansare NXDN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "Activare Mobile GPS", + "mobilegps_port" => "Port GPS", + "mobilegps_speed" => "Viteza Port GPS", + // Config Page - Firewall Configuration + "fw_dash" => "Acces Panou Control", + "fw_irc" => "Control Exterior ircDDBGateway", + "fw_ssh" => "Acces SSH", + // Config Page - Password + "user" => "Nume Utilizator", + "password" => "Parola", + "set_password" => "Setare Parola", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Moduri Activate ", + "net_status" => "Stare Retea", + "internet" => "Internet", + "radio_info" => "Info Radio", + "dstar_repeater" => "Repetor D-Star", + "dstar_net" => "Reteaua D-Star", + "dmr_repeater" => "Repetor DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "Reteaua YSF", + "p25_radio" => "P25 Radio", + "p25_net" => "Reteaua P25", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "Reteaua NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Ora", + "mode" => "Mod", + "callsign" => "Indicativ", + "target" => "Apel Catre", + "src" => "Src", // Prescurtare "Sursa" + "dur" => "Dur", // prescurtare "Durata" + "loss" => "Pierderi", + "ber" => "BER", // Prescurtare "Rata Eroare Biti" + // POCSAG Specific + "pocsag_list" => "Activitate Gateway DAPNET", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Mesaj", + // Dashboard - Extra Info + "group" => "Grup", + "logoff" => "Deconectare", + "info" => "Informatii", + "utot" => "UTOT", // Prescurtare User Timeout + "gtot" => "GTOT", // Prescurtare Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Ultimele 20 Apeluri Receptionate prin acest Gateway", + "local_tx_list" => "Ultimele 20 Apeluri care au accesat acest Gateway", + "active_starnet_groups" => "Grupuri Active Starnet", + "active_starnet_members" => "Membrii activi in Grupuri Starnet ", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "Informatii Legatura D-Star", + "service_status" => "Stare Serviciu" +); +?> diff --git a/admin/lang/slovenian_sl.php b/admin/lang/slovenian_sl.php new file mode 100644 index 0000000..0f0b44b --- /dev/null +++ b/admin/lang/slovenian_sl.php @@ -0,0 +1,157 @@ + "DV", + "configuration" => "Nastavitve", + "dashboard_for" => "Nadzorna plošča", + // Banner links + "dashboard" => "Nadzorna plošča", + "admin" => "Skrbniški način", + "power" => "Vklop/Izklop", + "update" => "Posodobitev", + "backup_restore" => "Varnostno kopiranje", + "factory_reset" => "Tovarniške nastavitve", + "live_logs" => "Dnevnik", + // Config page section headdings + "hardware_info" => "Informacije o strojni opremi prehoda", + "control_software" => "Nadzorna programska oprema", + "mmdvmhost_config" => "Nastavitve MMDVMHost", + "general_config" => "Splošne nastavitve", + "dmr_config" => "Nastavitve DMR", + "dstar_config" => "Nastavitve D-Star", + "ysf_config" => "Nastavitve Yaesu System Fusion", + "p25_config" => "Nastavitve P25", + "nxdn_config" => "Nastavitve NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Nastavitve POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Nastavitve brezžičnega omrežja", + "fw_config" => "Nastavitve požarnega zidu", + "remote_access_pw" => "Geslo za oddaljeni dostop", + // Config Page - Section General + "setting" => "Nastavitev", + "value" => "Vrednost", + "apply" => "Potrdi spremembe", + // Config Page - Gateway Hardware Information + "hostname" => "Ime gostitelja", + "kernel" => "Jedro", + "platform" => "Platforma", + "cpu_load" => "Obremenitev proc.", + "cpu_temp" => "Temperatura proc.", + // Config Page - Control Software + "controller_software" => "Programska oprema krmilnika", + "controller_mode" => "Način krmilnika", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Način DMR", + "d-star_mode" => "Način D-Star", + "ysf_mode" => "Način YSF", + "p25_mode" => "Način P25", + "nxdn_mode" => "Način NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Tip MMDVM zaslona", + "mode_hangtime" => "Obstanek načina", + // Config Page - General Configuration + "node_call" => "Klicni znak vozlišča", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frekvenca", + "lattitude" => "Zemljepisna širina", + "longitude" => "Zemljepisna dolžina", + "town" => "Kraj", + "country" => "Država", + "url" => "URL", + "radio_type" => "Vrsta sprejemnika/modema", + "node_type" => "Vrsta vozlišča", + "timezone" => "Časovni pas", + "dash_lang" => "Jezik nadzorne plošče", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister omrežje", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ omrežje", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Barvna Koda (CC)", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Klicni znak RPT1", + "dstar_rpt2" => "Klicni znak RPT2", + "dstar_irc_password" => "Geslo za oddaljeni dostop", + "dstar_default_ref" => "Privzeti reflektor", + "aprs_host" => "Gostitelj APRS", + "dstar_irc_lang" => "Jezik ircDDBGateway", + "dstar_irc_time" => "Napoved časa", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF zagonski gostitelj", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 zagonski gostitelj", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN zagonski gostitelj", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Dostop do nadzorne plošče", + "fw_irc" => "Dostop ircDDBGateway", + "fw_ssh" => "Dostop SSH", + // Config Page - Password + "user" => "Uporabniški ime", + "password" => "Geslo", + "set_password" => "Nastavi geslo", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Omogočeni načini", + "net_status" => "Stanje omrežja", + "internet" => "Internet", + "radio_info" => "Info o sprejemniku", + "dstar_repeater" => "Repetitor D-Star", + "dstar_net" => "D-Star Omrežje", + "dmr_repeater" => "Repetitor DMR", + "dmr_master" => "Master DMR", + "ysf_net" => "Omrežje YSF", + "p25_radio" => "Radio P25", + "p25_net" => "Omrežje P25", + "nxdn_radio" => "Radio NXDN", + "nxdn_net" => "Omrežje NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Čas", + "mode" => "Način", + "callsign" => "Klicni znak", + "target" => "Cilj", + "src" => "Vir", // Short version of "Source" + "dur" => "Dol", // Short version of "Duration" + "loss" => "Izguba", + "ber" => "DNB", // Short version of "Bit Error Rate" - delež napačnih bitov + // POCSAG Specific + "pocsag_list" => "Aktivnost DAPNET prehoda", + "pocsag_timeslot" => "Časovno okno (TS)", + "pocsag_msg" => "Sporočilo", + // Dashboard - Extra Info + "group" => "Skupina", + "logoff" => "Odjava", + "info" => "Informacija", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Aktivnost prehoda", + "local_tx_list" => "Lokalna RF aktivnost", + "active_starnet_groups" => "Aktivne skupine Starnet", + "active_starnet_members" => "Aktivni uporabniki Starnet", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Informacije", + "service_status" => "Stanje storitev" +); +?> diff --git a/admin/lang/spanish_es.php b/admin/lang/spanish_es.php new file mode 100644 index 0000000..0afd0a5 --- /dev/null +++ b/admin/lang/spanish_es.php @@ -0,0 +1,157 @@ + "Voz Digital", + "configuration" => "Configuracion", + "dashboard_for" => "Panel de control de", + // Banner links + "dashboard" => "Panel de Control", + "admin" => "Administrar", + "power" => "Reiniciar/Apagar", + "update" => "Actualizar", + "backup_restore" => "Backup/Restaurar copia de seguridad", + "factory_reset" => "Restaurar datos de fabrica", + "live_logs" => "Informes-Logs", + // Config page section headdings + "hardware_info" => "Informacion de hardware", + "control_software" => "Control de software", + "mmdvmhost_config" => "Configuracion de MMDVMHost", + "general_config" => "Configuracion General", + "dmr_config" => "Configuracion de DMR", + "dstar_config" => "Configuracion de DSTAR", + "ysf_config" => "Configuracion de Yaesu C4FM fusion", + "p25_config" => "Configuracion de P25", + "nxdn_config" => "Configuracion de NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuracion de POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuracion WIFI", + "fw_config" => "Configuracion del cortafuegos", + "remote_access_pw" => "Contraseña accceso Remoto", + // Config Page - Section General + "setting" => "Ajustes", + "value" => "Valor", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Plataforma", + "cpu_load" => "Carga de la CPU", + "cpu_temp" => "Temperatura CPU", + // Config Page - Control Software + "controller_software" => "Controlador Software", + "controller_mode" => "Controlador de Modo", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Modo DMR", + "d-star_mode" => "Modo D-Star", + "ysf_mode" => "Modo YSF", + "p25_mode" => "Modo P25", + "nxdn_mode" => "Modo NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Tipo Display", + "mode_hangtime" => "Modo tiempo de suspension", + // Config Page - General Configuration + "node_call" => "Nodo indicativo de llamada", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frecuencia RX/TX", + "lattitude" => "Latitud", + "longitude" => "Longitud", + "town" => "Ciudad", + "country" => "Pais", + "url" => "URL", + "radio_type" => "Radio/Tipo modem", + "node_type" => "Nodo Tipo", + "timezone" => "Zona horaria", + "dash_lang" => "Idioma del Panel de Control", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "Master de BrandMeister", + "bm_network" => "Red de BrandMeister", + "dmr_plus_master" => "Master de DMR+", + "dmr_plus_network" => "Red de DMR+", + "xlx_master" => "Master de XLX", + "xlx_enable" => "Habilitar Master XLX", + "dmr_cc" => "Codigo de color de DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 indicativo de llamada", + "dstar_rpt2" => "RPT2 indicativo de llamada", + "dstar_irc_password" => "contrasena de ircDDBGateway", + "dstar_default_ref" => "Reflector predeterminado", + "aprs_host" => "Servidor de APRS", + "dstar_irc_lang" => "Idioma de ircDDBGateway", + "dstar_irc_time" => "Intervalo de Balizas", + // Config Page - YSF Configuration + "ysf_startup_host" => "Servidor de Inicio YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Servidor de Inicio P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Servidor de Inicio NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Tablero de acceso", + "fw_irc" => "ircDDBGateway Remoto", + "fw_ssh" => "Acceso por SSH", + // Config Page - Password + "user" => "Nombre de usuario", + "password" => "Contrasena", + "set_password" => "Establecer contrasena", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modos habilitados", + "net_status" => "Estado de la red", + "internet" => "Internet", + "radio_info" => "Informacion de Radio", + "dstar_repeater" => "Repetidor de D-Star", + "dstar_net" => "Red de D-Star", + "dmr_repeater" => "Repetidor de DMR", + "dmr_master" => "Master de DMR", + "ysf_net" => "Red de YSF", + "p25_radio" => "Radio de P25", + "p25_net" => "Red de P25", + "nxdn_radio" => "Radio de NXDN", + "nxdn_net" => "Red de NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Hora", + "mode" => "Modo", + "callsign" => "Indicativo de llamada", + "target" => "Destino", + "src" => "SRC", //version corta de "fuente" + "dur" => "DUR", //version corta de "duracion" + "loss" => "Perdida", + "ber" => "BER", //version corta de "Error de bit" + // POCSAG Specific + "pocsag_list" => "Actividad de DAPNET Gateway", + "pocsag_timeslot" => "Slot de Tiempo", + "pocsag_msg" => "Mensaje", + // Dashboard - Extra Info + "group" => "Grupos", + "logoff" => "Finalizar", + "info" => "Informacion", + "utot" => "UTOT", //tiempo agotado para usuario + "gtot" => "GTOT", // tiempo agotado para grupo + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Ultimas 20 llamadas que accedieron al sistema", + "local_tx_list" => "Ultimas 20 llamadas que accedieron a ese puerto", + "active_starnet_groups" => "Grupos activos Starnet", + "active_starnet_members" => "Miembros activos del grupo Starnet", + "d-star_link_manager" => "Gestor de enlaces D-Star", + "d-star_link_status" => "Informacion de enlaces D-Star", + "service_status" => "Estado del servicio" +); +?> diff --git a/admin/lang/spanish_mx.php b/admin/lang/spanish_mx.php new file mode 100644 index 0000000..5d2c801 --- /dev/null +++ b/admin/lang/spanish_mx.php @@ -0,0 +1,157 @@ + "Voz Digital", + "configuration" => "Configuracion", + "dashboard_for" => "Tablero para", + // Banner links + "dashboard" => "Tablero", + "admin" => "Admin", + "power" => "Poder", + "update" => "Actualizar", + "backup_restore" => "Copia deseguridad_restaurar", + "factory_reset" => "Restablecimiento de fabrica", + "live_logs" => "Vivo Logs", + // Config page section headdings + "hardware_info" => "Puerta hardware Informacion", + "control_software" => "Control software", + "mmdvmhost_config" => "MMDVMHost Configuracion", + "general_config" => "General Configuracion", + "dmr_config" => "DMR Configuracion", + "dstar_config" => "D-Star Configuracion", + "ysf_config" => "Yaesu Configuracion de sistema fusion", + "p25_config" => "P25 Configuracion", + "nxdn_config" => "NXDN Configuracion", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Configuracion", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuracion Inalambrico", + "fw_config" => "Configuracion firewall", + "remote_access_pw" => "Remoto Accesso contrasena", + // Config Page - Section General + "setting" => "Ajustes", + "value" => "Valor", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Plataforma", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controlador Software", + "controller_mode" => "Controlador Modo", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Modo", + "d-star_mode" => "D-Star Modo", + "ysf_mode" => "YSF Modo", + "p25_mode" => "P25 Modo", + "nxdn_mode" => "NXDN Modo", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Tipo de muestra", + "mode_hangtime" => "Modo tiempo de suspension", + // Config Page - General Configuration + "node_call" => "Nodo signo de llamada", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frecuencia", + "lattitude" => "Latitud", + "longitude" => "Longitud", + "town" => "Ciudad", + "country" => "Pais", + "url" => "URL", + "radio_type" => "Radio/Tipo modem", + "node_type" => "Nodo Tipo", + "timezone" => "Sistema zona horaria", + "dash_lang" => "Tablero de ldiomas", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister red", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ red", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master habilitar", + "dmr_cc" => "DMR Codigo de color", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 signo de llamada", + "dstar_rpt2" => "RPT2 signo de llamada", + "dstar_irc_password" => "ircDDBGateway contrasena", + "dstar_default_ref" => "Reflector predeterminado", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Language", + "dstar_irc_time" => "Tiempo Anuncios", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Lanzamiento Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Lanzamiento Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Lanzamiento Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Tablero de acceso", + "fw_irc" => "ircDDBGateway Remoto", + "fw_ssh" => "SSH Acceso", + // Config Page - Password + "user" => "Usuario Nombre", + "password" => "Contrasena", + "set_password" => "Set contrasena", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modos habilitado", + "net_status" => "Estatus de red", + "internet" => "Internet", + "radio_info" => "Radio Informacion", + "dstar_repeater" => "D-Star Repetidor", + "dstar_net" => "D-Star red", + "dmr_repeater" => "DMR Repetidor", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF red", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 red", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN red", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Time", + "mode" => "Modo", + "callsign" => "signo de llamada", + "target" => "Objetivo", + "src" => "Src", //version corta de "fuente" + "dur" => "Dur", //version corta de "duracion" + "loss" => "Perdida", + "ber" => "BER", //version corta de "Error de bit" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Grupos", + "logoff" => "Finalizar", + "info" => "Informacion", + "utot" => "UTOT", //tiempo agotado para usuario + "gtot" => "GTOT", // tiempo agotado para grupo + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Ultimos 20 llamadas escuchadas atraves de este puerto", + "local_tx_list" => "Ultimo 20 llamadas que accesaron este puerto", + "active_starnet_groups" => "Activo grupo Starnet Groups", + "active_starnet_members" => "Activo miembros de grupo Starnet", + "d-star_link_manager" => "D-Star gestar de enlaces", + "d-star_link_status" => "D-Star Informacion de enlaces", + "service_status" => "Estado servicio" +); +?> diff --git a/admin/lang/swedish_se.php b/admin/lang/swedish_se.php new file mode 100644 index 0000000..7f32cd7 --- /dev/null +++ b/admin/lang/swedish_se.php @@ -0,0 +1,158 @@ + "Digital Voice", + "configuration" => "Konfiguration", + "dashboard_for" => "Dashboard för", + // Banner links + "dashboard" => "Dashboard", + "admin" => "Admin", + "power" => "Power", + "update" => "Uppdatera", + "backup_restore" => "Backup/Återställ", + "factory_reset" => "Fabriksåterställning", + "live_logs" => "Liveloggar", + // Config page section headdings + "hardware_info" => "Gateway Hårdvaruinformation", + "control_software" => "Kontroll Mjukvara", + "mmdvmhost_config" => "MMDVMHost Konfiguration", + "general_config" => "Generell Konfiguration", + "dmr_config" => "DMR Konfiguration", + "dstar_config" => "D-Star Konfiguration", + "ysf_config" => "Yaesu System Fusion Konfiguration", + "p25_config" => "P25 Konfiguration", + "nxdn_config" => "NXDN Konfiguration", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Konfiguration", + "mobilegps_config" => "Mobil GPS Konfiguration", + "wifi_config" => "WiFi Konfiguration", + "fw_config" => "Brandvägg Konfiguration", + "remote_access_pw" => "Remote Access Password", + // Config Page - Section General + "setting" => "Inställning", + "value" => "Värde", + "apply" => "Spara", + // Config Page - Gateway Hardware Information + "hostname" => "Värdnamn", + "kernel" => "Kärna", + "platform" => "Plattform", + "cpu_load" => "CPU Last", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller Software", + "controller_mode" => "Controller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Displaytyp", + "mode_hangtime" => "Mode Hängtid", + // Config Page - General Configuration + "node_call" => "Node Signal", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radiofrekvens", + "lattitude" => "Latitud", + "longitude" => "Longitud", + "town" => "Stad", + "country" => "Land", + "url" => "URL", + "radio_type" => "Radio-/Modemtyp", + "node_type" => "Nodetyp", + "timezone" => "Systemets Tidzon", + "dash_lang" => "Dashboard Språk", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Colour Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Signal", + "dstar_rpt2" => "RPT2 Signal", + "dstar_irc_password" => "Lösen ircDDB", + "dstar_default_ref" => "Default Reflektor", + "aprs_host" => "APRS-värd", + "dstar_irc_lang" => "ircDDBGateway Språk", + "dstar_irc_time" => "Tidsannonseringar", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startvärd", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startvärd", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startvärd", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobilGPS På", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Hastighet", + // Config Page - Firewall Configuration + "fw_dash" => "Dashboard Access", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH-access", + // Config Page - Password + "user" => "Användarnamn", + "password" => "Lösenord", + "set_password" => "Byt Lösenord", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Moder Aktiverade", + "net_status" => "Nätverkstatus", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Nätverk", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Nätverk", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Nätverk", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Nätverk", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Tid", + "mode" => "Mode", + "callsign" => "Signal", + "target" => "Mål", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gatewayaktivitet", + "pocsag_timeslot" => "Tidslucka", + "pocsag_msg" => "Meddelande", + // Dashboard - Extra Info + "group" => "Grupp", + "logoff" => "Logga Av", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Gatewayaktivitet", + "local_tx_list" => "Lokal RF-aktivitet", + "active_starnet_groups" => "Aktiva Starnet Grupper", + "active_starnet_members" => "Aktiva Starnet Gruppmedlemmar", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Information", + "service_status" => "Service Status" +); +?> diff --git a/admin/lang/thai_th.php b/admin/lang/thai_th.php new file mode 100644 index 0000000..7579880 --- /dev/null +++ b/admin/lang/thai_th.php @@ -0,0 +1,157 @@ + "Digital Voice", + "configuration" => "ตั้งค่า", + "dashboard_for" => "แผงควบคุมสำหรับ", + // Banner links + "dashboard" => "แผงควบคุม", + "admin" => "ผู้ดูแล", + "power" => "เพาเวอร์", + "update" => "อัพเดท", + "backup_restore" => "สำรองข้อมูล", + "factory_reset" => "รีเซ็ต", + "live_logs" => "ประวัติการติดต่อ (สด)", + // Config page section headdings + "hardware_info" => "รายละเอียดของอุปกรณ์เกตเวย์", + "control_software" => "ซอฟต์แวร์ควบคุม", + "mmdvmhost_config" => "ตั้งค่า MMDVMHost", + "general_config" => "ตั้งค่าทั่วไป", + "dmr_config" => "ตั้งค่า DMR", + "dstar_config" => "ตั้งค่า D-Star", + "ysf_config" => "ตั้งค่า Yaesu System Fusion", + "p25_config" => "ตั้งค่า P25", + "nxdn_config" => "ตั้งค่า NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "ตั้งค่า POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "ตั้งค่าวายฟาย", + "fw_config" => "ตั้งค่าระบบป้องกัน", + "remote_access_pw" => "ตั้งรหัสผ่าน", + // Config Page - Section General + "setting" => "ตั้งค่า", + "value" => "ค่า", + "apply" => "ยืนยัน", + // Config Page - Gateway Hardware Information + "hostname" => "ชื่ออุปกรณ์", + "kernel" => "เคอร์เนิล", + "platform" => "อุปกรณ์", + "cpu_load" => "โหลด CPU", + "cpu_temp" => "อุณหภูมิ CPU", + // Config Page - Control Software + "controller_software" => "ชนิดของอุปกรณ์", + "controller_mode" => "โหมดการทำงาน", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR", + "d-star_mode" => "D-Star", + "ysf_mode" => "YSF", + "p25_mode" => "P25", + "nxdn_mode" => "NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "หน้าจอ MMDVM", + "mode_hangtime" => "Hangtime", + // Config Page - General Configuration + "node_call" => "นามเรียกขานของสถานี", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "ความถี่ที่ใช้งาน", + "lattitude" => "ละติจูด", + "longitude" => "ลองจิจูด", + "town" => "เมือง", + "country" => "ประเทศ", + "url" => "URL", + "radio_type" => "ชนิดของอุปกรณ์", + "node_type" => "รูปแบบของสถานี", + "timezone" => "เขตเวลาที่ใช้", + "dash_lang" => "ภาษาสำหรับแผงควบคุม", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Color Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "นามเรียกขาน RPT1", + "dstar_rpt2" => "นามเรียกขาน RPT2", + "dstar_irc_password" => "รหัสผ่านเข้าถึงจากภายนอก", + "dstar_default_ref" => "ค่าเริ่มต้นของ Reflector", + "aprs_host" => "เซิร์ฟเวอร์ APRS", + "dstar_irc_lang" => "ภาษาสำหรับ ircDDBGateway", + "dstar_irc_time" => "ประกาศเวลาทุกชั่วโมง", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startup Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startup Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startup Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "การเข้าถึงแผงควบคุม", + "fw_irc" => "การเข้าถึง ircDDBGateway", + "fw_ssh" => "การเข้าถึง SSH", + // Config Page - Password + "user" => "ชื่อผู้ใช้", + "password" => "รหัสผ่าน", + "set_password" => "ยืนยัน", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "โหมดที่เปิดใช้งาน", + "net_status" => "สถานะเครือข่าย", + "internet" => "อินเตอร์เน็ต", + "radio_info" => "ข้อมูลวิทยุ", + "dstar_repeater" => "รีพีทเตอร์ D-Star", + "dstar_net" => "เครือข่าย D-Star", + "dmr_repeater" => "รีพีทเตอร์ DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "เครือข่าย YSF", + "p25_radio" => "วิทยุ P25", + "p25_net" => "เครือข่าย P25", + "nxdn_radio" => "วิทยุ NXDN", + "nxdn_net" => "เครือข่าย NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "เวลา", + "mode" => "โหมด", + "callsign" => "นามเรียกขาน", + "target" => "เป้าหมาย", + "src" => "สัญญาณจาก", // Short version of "Source" + "dur" => "ระยะเวลา", // Short version of "Duration" + "loss" => "สัญญาณสูญเสีย", + "ber" => "สัญญาณผิดพลาด", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "กลุ่ม", + "logoff" => "ออกจากระบบ", + "info" => "ข้อมูล", + "utot" => "ผู้ใช้", // Short for User Timeout + "gtot" => "กลุ่ม", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "ความเคลื่อนไหวของเกตเวย์", + "local_tx_list" => "ความเคลื่อนไหวของคลื่นที่รับได้", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "จัดการการเชื่อมต่อของ D-Star", + "d-star_link_status" => "ข้อมูลการเชื่อมต่อของ D-Star", + "service_status" => "สถานะของระบบ" +); +?> diff --git a/admin/lang/turkish_tr.php b/admin/lang/turkish_tr.php new file mode 100644 index 0000000..d0b5316 --- /dev/null +++ b/admin/lang/turkish_tr.php @@ -0,0 +1,157 @@ + "Dijital Ses", + "configuration" => "Konfigürasyon", + "dashboard_for" => "Panosu", + // Banner links + "dashboard" => "Pano", + "admin" => "Yönetici", + "power" => "Güç", + "update" => "Güncelle", + "backup_restore" => "Yedekle/Geriyükle", + "factory_reset" => "Fabrika Ayarları", + "live_logs" => "Sistem Günlüğü", + // Config page section headdings + "hardware_info" => "Ağ Geçidi Donanım Bilgisi", + "control_software" => "Kontrolcü Yazılımı", + "mmdvmhost_config" => "MMDVMHost Konfigürasyonu", + "general_config" => "Genel Konfigürasyon", + "dmr_config" => "DMR Konfigürasyonu", + "dstar_config" => "D-Star Konfigürasyonu", + "ysf_config" => "Yaesu System Fusion Konfigürasyonu", + "p25_config" => "P25 Konfigürasyonu", + "nxdn_config" => "NXDN Konfigürasyonu", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Konfigürasyonu", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Kablosuz Konfigürasyonu", + "fw_config" => "Güv.Duv. Konfigürasyonu", + "remote_access_pw" => "Uzak Erişim Parolası", + // Config Page - Section General + "setting" => "Ayar", + "value" => "Değer", + "apply" => "Değişiklikleri Uygula", + // Config Page - Gateway Hardware Information + "hostname" => "Sistem Adı", + "kernel" => "Çekirdek Sürümü", + "platform" => "Altyapı", + "cpu_load" => "CPU Kullanımı", + "cpu_temp" => "CPU Sıcaklığı", + // Config Page - Control Software + "controller_software" => "Kontrolcünün Yazılımı", + "controller_mode" => "Kontrolcünün Modu", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Modu", + "d-star_mode" => "D-Star Modu", + "ysf_mode" => "YSF Modu", + "p25_mode" => "P25 Modu", + "nxdn_mode" => "NXDN Modu", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Ekran Tipi", + "mode_hangtime" => "Mod Askı Süresi", + // Config Page - General Configuration + "node_call" => "Çağrı İşaretiniz", + "dmr_id" => "CCS7/DMR No", + "radio_freq" => "Radyo Frekansı", + "lattitude" => "Enlem", + "longitude" => "Boylam", + "town" => "Şehir", + "country" => "Ülke", + "url" => "URL", + "radio_type" => "Radyo/Modem Tipi", + "node_type" => "Yayın Tipi", + "timezone" => "Sistem Saati Dilimi", + "dash_lang" => "Pano Dili", + // Config Page - DMR Configuration + "dmr_master" => "DMR Sunucu (MMDVMHost)", + "bm_master" => "BrandMeister Sunucu", + "bm_network" => "BrandMeister Ağı", + "dmr_plus_master" => "DMR+ Sunucu", + "dmr_plus_network" => "DMR+ Ağı", + "xlx_master" => "XLX Sunucu", + "xlx_enable" => "XLX Sunucu Etkinleştirme", + "dmr_cc" => "DMR Renk Kodu", + "dmr_embeddedlconly" => "DMR GömülüLC", + "dmr_dumptadata" => "DMR TAVeriDökümü", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Çağrı İşareti", + "dstar_rpt2" => "RPT2 Çağrı İşareti", + "dstar_irc_password" => "Uzak Erişim Parolası", + "dstar_default_ref" => "Varsayılan Yansıtıcı", + "aprs_host" => "APRS Sunucusu", + "dstar_irc_lang" => "ircDDBAğGeçidi Dili", + "dstar_irc_time" => "Bildirimler", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF İşletme Ağı", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 İşletme Ağı", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN İşletme Ağı", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Pano Erişimi", + "fw_irc" => "ircDDBAğGeçidi Erişimi", + "fw_ssh" => "SSH Erişimi", + // Config Page - Password + "user" => "Kullanıcı Adı", + "password" => "Parola", + "set_password" => "Parolayı Uygula", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Etkin Modlar", + "net_status" => "Ağ Durumu", + "internet" => "İnternet", + "radio_info" => "Radyo Bilgisi", + "dstar_repeater" => "D-Star Röle", + "dstar_net" => "D-Star Ağı", + "dmr_repeater" => "DMR Röle", + "dmr_master" => "DMR Sunucu", + "ysf_net" => "YSF Ağı", + "p25_radio" => "P25 Radyo", + "p25_net" => "P25 Ağı", + "nxdn_radio" => "NXDN Radyo", + "nxdn_net" => "NXDN Ağı", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Zaman", + "mode" => "Mod", + "callsign" => "Çağrı İşareti", + "target" => "Hedef", + "src" => "Kynk", // Short version of "Source" + "dur" => "Süre", // Short version of "Duration" + "loss" => "Kayıp", + "ber" => "BHO", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Ağ Geçidi Etkinliği", + "pocsag_timeslot" => "Zaman Aralığı", + "pocsag_msg" => "Mesaj", + // Dashboard - Extra Info + "group" => "Grup", + "logoff" => "Oturum Kapat", + "info" => "Ayrıntılar", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Ağ Geçidi Etkinliği", + "local_tx_list" => "Yerel RF Etkinliği", + "active_starnet_groups" => "Aktif Starnet Grupları", + "active_starnet_members" => "Aktif Starnet Grup Üyeleri", + "d-star_link_manager" => "D-Star Bağlantı Yöneticisi", + "d-star_link_status" => "D-Star Bağlantı Ayrıntıları", + "service_status" => "Servis Durumu" +); +?> diff --git a/admin/live_modem_log.php b/admin/live_modem_log.php index bd5e31d..3db58a0 100644 --- a/admin/live_modem_log.php +++ b/admin/live_modem_log.php @@ -1,25 +1,4 @@ @@ -81,13 +60,13 @@ if ($_SERVER["PHP_SELF"] == "/admin/live_modem_log.php") { - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['live_logs'];?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['live_logs'];?> @@ -107,11 +86,10 @@ if ($_SERVER["PHP_SELF"] == "/admin/live_modem_log.php") { -
-
Pi-Star: /
-

Pi-Star

+
CDN: /
+

CDN

| | @@ -121,17 +99,11 @@ if ($_SERVER["PHP_SELF"] == "/admin/live_modem_log.php") {

- - - - -
Starting logging, please wait...
Download the log: here
+

+
+
Starting logging, please wait...
+
Download the log: (.log)
-
@@ -139,3 +111,4 @@ if ($_SERVER["PHP_SELF"] == "/admin/live_modem_log.php") { diff --git a/admin/mmdvmhost b/admin/mmdvmhost deleted file mode 100644 index e877e16..0000000 --- a/admin/mmdvmhost +++ /dev/null @@ -1 +0,0 @@ -../mmdvmhost/ \ No newline at end of file diff --git a/admin/mmdvmhost/bm_links.php b/admin/mmdvmhost/bm_links.php new file mode 100644 index 0000000..0cdfb09 --- /dev/null +++ b/admin/mmdvmhost/bm_links.php @@ -0,0 +1,113 @@ += 200 ) { $bmAPIkeyV2 = $bmAPIkey; unset($bmAPIkey); } + } + + //Load the dmrgateway config file + $dmrGatewayConfigFile = '/etc/dmrgateway'; + if (fopen($dmrGatewayConfigFile,'r')) { $configdmrgateway = parse_ini_file($dmrGatewayConfigFile, true); } + + // Get the current DMR Master from the config + $dmrMasterHost = getConfigItem("DMR Network", "Address", $mmdvmconfigs); + if ( $dmrMasterHost == '127.0.0.1' ) { + $dmrMasterHost = $configdmrgateway['DMR Network 1']['Address']; + if (isset($configdmrgateway['DMR Network 1']['Id'])) { $dmrID = $configdmrgateway['DMR Network 1']['Id']; } + } elseif (getConfigItem("DMR", "Id", $mmdvmconfigs)) { + $dmrID = getConfigItem("DMR", "Id", $mmdvmconfigs); + } else { + $dmrID = getConfigItem("General", "Id", $mmdvmconfigs); + } + + // Store the DMR Master IP, we will need this for the JSON lookup + $dmrMasterHostIP = $dmrMasterHost; + + // Make sure the master is a BrandMeister Master + $dmrMasterFile = fopen("/usr/local/etc/DMR_Hosts.txt", "r"); + while (!feof($dmrMasterFile)) { + $dmrMasterLine = fgets($dmrMasterFile); + $dmrMasterHostF = preg_split('/\s+/', $dmrMasterLine); + if ((strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { + if ($dmrMasterHost == $dmrMasterHostF[2]) { $dmrMasterHost = str_replace('_', ' ', $dmrMasterHostF[0]); } + } + } + + if (substr($dmrMasterHost, 0, 2) == "BM") { + + // Use BM API to get information about current TGs + $jsonContext = stream_context_create(array('http'=>array('timeout' => 2, 'header' => 'User-Agent: Pi-Star Dashboard for '.$dmrID) )); // Add Timout and User Agent to include DMRID + if (isset($bmAPIkeyV2)) { + $json = json_decode(@file_get_contents("https://api.brandmeister.network/v2/device/$dmrID/profile", true, $jsonContext)); + } else { + $json = json_decode(@file_get_contents("https://api.brandmeister.network/v1.0/repeater/?action=PROFILE&q=$dmrID", true, $jsonContext)); + } + + // Set some Variable + $bmStaticTGList = ""; + $bmDynamicTGList = ""; + + // Pull the information form JSON + if (isset($json->staticSubscriptions)) { $bmStaticTGListJson = $json->staticSubscriptions; + foreach($bmStaticTGListJson as $staticTG) { + if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) && $staticTG->slot == "1") { + $bmStaticTGList .= "TG".$staticTG->talkgroup."(".$staticTG->slot.") "; + } + else if (getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $staticTG->slot == "2") { + $bmStaticTGList .= "TG".$staticTG->talkgroup."(".$staticTG->slot.") "; + } + else if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" && getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $staticTG->slot == "0") { + $bmStaticTGList .= "TG".$staticTG->talkgroup." "; + } + } + $bmStaticTGList = wordwrap($bmStaticTGList, 15, "
\n"); + if (preg_match('/TG/', $bmStaticTGList) == false) { $bmStaticTGList = "None"; } + } else { $bmStaticTGList = "None"; } + if (isset($json->dynamicSubscriptions)) { $bmDynamicTGListJson = $json->dynamicSubscriptions; + foreach($bmDynamicTGListJson as $dynamicTG) { + if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) && $dynamicTG->slot == "1") { + $bmDynamicTGList .= "TG".$dynamicTG->talkgroup."(".$dynamicTG->slot.") "; + } + else if (getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $dynamicTG->slot == "2") { + $bmDynamicTGList .= "TG".$dynamicTG->talkgroup."(".$dynamicTG->slot.") "; + } + else if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" && getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $dynamicTG->slot == "0") { + $bmDynamicTGList .= "TG".$dynamicTG->talkgroup." "; + } + } + $bmDynamicTGList = wordwrap($bmDynamicTGList, 15, "
\n"); + if (preg_match('/TG/', $bmDynamicTGList) == false) { $bmDynamicTGList = "None"; } + } else { $bmDynamicTGList = "None"; } + + echo 'Active BrandMeister Connections + + + + + + + '."\n"; + + echo ' '."\n"; + echo ' '; + echo ''; + echo ''; + echo ''; + echo ''."\n"; + echo '
'.$lang['bm_master'].'Connected MasterRepeater IDThe ID for this Repeater/HotspotStatic TGsStatically linked talkgroupsDynamic TGsDynamically linked talkgroups
'.$dmrMasterHost.''.$dmrID.''.$bmStaticTGList.''.$bmDynamicTGList.'
'."\n"; + echo '
'."\n"; + } +} +?> diff --git a/admin/mmdvmhost/bm_manager.php b/admin/mmdvmhost/bm_manager.php new file mode 100644 index 0000000..44efd80 --- /dev/null +++ b/admin/mmdvmhost/bm_manager.php @@ -0,0 +1,137 @@ += 200 ) { $bmAPIkeyV2 = $bmAPIkey; unset($bmAPIkey); } + } + + //Load the dmrgateway config file + $dmrGatewayConfigFile = '/etc/dmrgateway'; + if (fopen($dmrGatewayConfigFile,'r')) { $configdmrgateway = parse_ini_file($dmrGatewayConfigFile, true); } + + // Get the current DMR Master from the config + $dmrMasterHost = getConfigItem("DMR Network", "Address", $mmdvmconfigs); + if ( $dmrMasterHost == '127.0.0.1' ) { + $dmrMasterHost = $configdmrgateway['DMR Network 1']['Address']; + if (isset($configdmrgateway['DMR Network 1']['Id'])) { $dmrID = $configdmrgateway['DMR Network 1']['Id']; } + } elseif (getConfigItem("DMR", "Id", $mmdvmconfigs)) { + $dmrID = getConfigItem("DMR", "Id", $mmdvmconfigs); + } else { + $dmrID = getConfigItem("General", "Id", $mmdvmconfigs); + } + + // Store the DMR Master IP, we will need this for the JSON lookup + $dmrMasterHostIP = $dmrMasterHost; + + // Make sure the master is a BrandMeister Master + $dmrMasterFile = fopen("/usr/local/etc/DMR_Hosts.txt", "r"); + while (!feof($dmrMasterFile)) { + $dmrMasterLine = fgets($dmrMasterFile); + $dmrMasterHostF = preg_split('/\s+/', $dmrMasterLine); + if ((strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { + if ($dmrMasterHost == $dmrMasterHostF[2]) { $dmrMasterHost = str_replace('_', ' ', $dmrMasterHostF[0]); } + } + } + if (substr($dmrMasterHost, 0, 2) == "BM") { + if (isset($bmAPIkeyV2) && !empty($_POST) && (isset($_POST["dropDyn"]) || isset($_POST["dropQso"]) || isset($_POST["tgSubmit"]))) : // Data has been posted for this page + $bmAPIurl = 'https://api.brandmeister.network/v2/device/'; + // Are we a repeater + if ( getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" ) { + unset($_POST["TS"]); + $targetSlot = "0"; + } else { + $targetSlot = $_POST["TS"]; + } + // Set the API URLs + if (isset($_POST["dropDyn"])) { $bmAPIurl = $bmAPIurl.$dmrID."/action/dropDynamicGroups/".$targetSlot; $method = "GET"; } + if (isset($_POST["dropQso"])) { $bmAPIurl = $bmAPIurl.$dmrID."/action/dropCallRoute/".$targetSlot; $method = "GET"; } + if ( (isset($_POST["tgNr"])) && (isset($_POST["tgSubmit"])) ) { $targetTG = preg_replace("/[^0-9]/", "", $_POST["tgNr"]); } + if ( ($_POST["TGmgr"] == "ADD") && (isset($_POST["tgSubmit"])) ) { $bmAPIurl = $bmAPIurl.$dmrID."/talkgroup/"; $method = "POST"; } + if ( ($_POST["TGmgr"] == "DEL") && (isset($_POST["tgSubmit"])) ) { $bmAPIurl = $bmAPIurl.$dmrID."/talkgroup/".$targetSlot."/".$targetTG; $method = "DELETE"; } + + // Build the Data + $postHeaders = array( + 'Content-Type: application/json', + 'Accept: application/json', + 'Authorization: Bearer '.$bmAPIkeyV2, + 'User-Agent: Pi-Star Dashboard for '.$dmrID, + ); + $opts = array( + 'http' => array( + 'method' => $method, + //'header' => $postHeaders, + 'header' => implode("\r\n", $postHeaders), + 'password' => '', + 'success' => '', + 'timeout' => 2, + ), + ); + + // If we are adding a TG + if ( (!isset($_POST["dropDyn"])) && (!isset($_POST["dropQso"])) && isset($targetTG) && $_POST["TGmgr"] == "ADD" ) { + $postDataTG = array( + 'slot' => $targetSlot, + 'group' => $targetTG + ); + $postData = json_encode($postDataTG); + $postHeaders[] = 'Content-Length: '.strlen($postData); + $opts['http']['content'] = $postData; + } + + // Make the request + $context = stream_context_create($opts); + $result = @file_get_contents($bmAPIurl, false, $context); + $feeback=json_decode($result); + // Output to the browser + echo 'BrandMeister Manager'."\n"; + echo "\n\n\n
Command Output
"; + if (isset($feeback)) { print "BrandMeister APIv2: OK"; } else { print "BrandMeister APIv2: No Response"; } + echo "
\n"; + echo "
\n"; + // Clean up... + unset($_POST); + echo ''; + + else: // Do this when we are not handling post data + // If there is a BM API Key + if (isset($bmAPIkeyV2)) { + echo 'BrandMeister Manager'."\n"; + echo '
'."\n"; + echo ''."\n"; + echo ' + + + + + '."\n"; + echo ' '; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''."\n"; + echo ' '; + echo ''; + echo ''."\n"; + echo '
ActionTake Action
'."\n"; + echo '
'."\n"; + } + endif; + } + } +} + diff --git a/admin/mmdvmhost/functions.php b/admin/mmdvmhost/functions.php new file mode 100644 index 0000000..65e9cb6 --- /dev/null +++ b/admin/mmdvmhost/functions.php @@ -0,0 +1,1480 @@ + up to $maxMatches matching lines + */ +function pistar_log_tail_match($path, $matchRegex, $excludeRegex, + $maxMatches, $stripFirstField = false, + $reverse = false) +{ + $bufSize = 262144; // 256 KB tail window — see docblock above + + $fp = @fopen($path, 'rb'); + if ($fp === false) { + return array(); + } + if (fseek($fp, 0, SEEK_END) !== 0) { + fclose($fp); + return array(); + } + $fileSize = ftell($fp); + if ($fileSize === false || $fileSize === 0) { + fclose($fp); + return array(); + } + + $readSize = min($bufSize, $fileSize); + $readFrom = $fileSize - $readSize; + if (fseek($fp, $readFrom, SEEK_SET) !== 0) { + fclose($fp); + return array(); + } + $buf = fread($fp, $readSize); + fclose($fp); + if ($buf === false || $buf === '') { + return array(); + } + + // If we started reading mid-file, the first line in $buf is + // almost certainly cut by the chunk boundary. Drop bytes up + // to and including the first newline so we never feed a + // partial line to the regex pass. (When $readFrom == 0 we're + // at the start of the file — the first line is real, keep it.) + if ($readFrom > 0) { + $nl = strpos($buf, "\n"); + if ($nl === false) { + return array(); + } + $buf = substr($buf, $nl + 1); + } + + $matched = array(); + $lines = explode("\n", $buf); + foreach ($lines as $line) { + if ($line === '') continue; + if (!preg_match($matchRegex, $line)) continue; + if ($excludeRegex !== '' && preg_match($excludeRegex, $line)) continue; + $matched[] = $line; + } + + if (count($matched) > $maxMatches) { + $matched = array_slice($matched, -$maxMatches); + } + if ($stripFirstField) { + foreach ($matched as &$mline) { + $sp = strpos($mline, ' '); + if ($sp !== false) { + $mline = substr($mline, $sp + 1); + } + } + unset($mline); + } + if ($reverse) { + $matched = array_reverse($matched); + } + return $matched; +} + +function getMMDVMConfig() +{ + // /etc/mmdvmhost is read once per request and cached for the + // remainder. The top-level init at the bottom of this file + // calls us once, and getDSTARLinks() calls us again on D-Star + // hosts — same request, same file, identical result. The + // static cache resets at request shutdown (PHP-FPM does not + // preserve userland state between requests), so this is purely + // an in-request dedup, not a cross-request cache. + static $cached; + if ($cached !== null) { + return $cached; + } + $cached = array(); + if ($configs = @fopen(MMDVMINIPATH."/".MMDVMINIFILENAME, 'r')) { + while ($config = fgets($configs)) { + array_push($cached, trim($config, " \t\n\r\0\x0B")); + } + fclose($configs); + } + return $cached; +} + +function getDMRHostsLines() +{ + // /usr/local/etc/DMR_Hosts.txt is the BrandMeister master list, + // typically 3-6K lines on SD storage. repeaterinfo.php scans it + // twice per request when both DMR and YSF2DMR are enabled (lines + // 243-282 and 379-389) — both consumers iterate the same lines + // looking for an IP→name match. Read once into an in-memory + // line array; foreach() across it is free. + // + // Per-request scope only (PHP-FPM resets userland state between + // requests). file() loads the whole file in one syscall, which + // is cheaper than ~6K fgets() calls and roughly the same memory + // (~400-800 KB for the typical hosts file — fine on the 512 MB+ + // Pi-Star supports). + static $cached; + if ($cached !== null) { + return $cached; + } + $cached = @file('/usr/local/etc/DMR_Hosts.txt', + FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + if ($cached === false) { + $cached = array(); + } + return $cached; +} + +function getTGNameMap() +{ + // /usr/local/etc/TGList_CN.json is this operator's own domestic + // talkgroup registry, synced once a day by pistar-cn-tglist-sync + // from https://860.radiowo.com/api/v1/talkgroups. MMDVMHost's log + // only ever prints the numeric ID ("to TG 86990"), never a name, + // so lh.php needs this map to show what that network's own + // dashboard shows for free. + // + // Deliberately CN-only: BrandMeister's global TGList_BM.txt is NOT + // read/merged here — this operator's TG IDs are a private/domestic + // numbering space, and mixing in BM's global names would show the + // wrong name for an ID that means something else on this network. + // + // Per-request scope only (PHP-FPM resets userland state between + // requests); cheap enough (a few dozen entries) to re-parse each + // request. + static $cached; + if ($cached !== null) { + return $cached; + } + $cached = array(); + $json = @file_get_contents('/usr/local/etc/TGList_CN.json'); + if ($json !== false) { + $rows = json_decode($json, true); + if (is_array($rows)) { + foreach ($rows as $row) { + if (!is_array($row)) { continue; } + if (!isset($row['tg_id'], $row['name'])) { continue; } + if (!is_numeric($row['tg_id'])) { continue; } + $cached[(int)$row['tg_id']] = (string)$row['name']; + } + } + } + return $cached; +} + +function getYSFGatewayConfig() +{ + // loads /etc/ysfgateway into array for further use + $conf = array(); + if ($configs = @fopen(YSFGATEWAYINIPATH."/".YSFGATEWAYINIFILENAME, 'r')) { + while ($config = fgets($configs)) { + array_push($conf, trim ( $config, " \t\n\r\0\x0B")); + } + fclose($configs); + } + return $conf; +} + +function getP25GatewayConfig() +{ + // loads /etc/p25gateway into array for further use + $conf = array(); + if ($configs = @fopen(P25GATEWAYINIPATH."/".P25GATEWAYINIFILENAME, 'r')) { + while ($config = fgets($configs)) { + array_push($conf, trim ( $config, " \t\n\r\0\x0B")); + } + fclose($configs); + } + return $conf; +} + +function getNXDNGatewayConfig() +{ + // loads /etc/nxdngateway into array for further use + $conf = array(); + if ($configs = @fopen('/etc/nxdngateway', 'r')) { + while ($config = fgets($configs)) { + array_push($conf, trim ( $config, " \t\n\r\0\x0B")); + } + fclose($configs); + } + return $conf; +} + +function getM17GatewayConfig() +{ + // loads /etc/m17gateway into array for further use + $conf = array(); + if ($configs = @fopen('/etc/m17gateway', 'r')) { + while ($config = fgets($configs)) { + array_push($conf, trim ( $config, " \t\n\r\0\x0B")); + } + fclose($configs); + } + return $conf; +} + +function getDAPNETGatewayConfig() +{ + // loads /etc/dapnetgateway into array for further use + $conf = array(); + if ($configs = @fopen('/etc/dapnetgateway', 'r')) { + while ($config = fgets($configs)) { + array_push($conf, trim ( $config, " \t\n\r\0\x0B")); + } + fclose($configs); + } + return $conf; +} + +function getConfigItem($section, $key, $configs) +{ + // retrieves the corresponding config-entry within a [section] + $sectionpos = array_search("[" . $section . "]", $configs) + 1; + $len = count($configs); + while(startsWith($configs[$sectionpos],$key."=") === false && $sectionpos <= ($len) ) { + if (startsWith($configs[$sectionpos],"[")) { + return null; + } + $sectionpos++; + } + + return substr($configs[$sectionpos], strlen($key) + 1); +} + +function getEnabled ($mode, $mmdvmconfigs) +{ + // returns enabled/disabled-State of mode + return getConfigItem($mode, "Enable", $mmdvmconfigs); +} + +function checkDMRLogin ($dmrDaemon) +{ + if ($dmrDaemon == "MMDVMHost") { + if (file_exists(MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log")) { + $logPath = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log"; + $logCheckMMDVMHostDMRLogin = `tail -n 5 $logPath | awk '/master/ && /successfully/ || /master/ && /failed/' | tail -n 1`; + if (strpos($logCheckMMDVMHostDMRLogin, "success")) { return 0; } + elseif (strpos($logCheckMMDVMHostDMRLogin, "fail")) { return 1; } + else { return 0; } + } + } + elseif ($dmrDaemon == "DMRGateway") { + if (file_exists("/var/log/pi-star/DMRGateway-".gmdate("Y-m-d").".log")) { + $logPath = "/var/log/pi-star/DMRGateway-".gmdate("Y-m-d").".log"; + $logCheckDMRGatewayDMRLogin = `tail -n 5 $logPath | awk '/master/ && /successfully/ || /master/ && /failed/' | tail -n 1`; + if (strpos($logCheckDMRGatewayDMRLogin, "success")) { return 0; } + elseif (strpos($logCheckDMRGatewayDMRLogin, "fail")) { return 1; } + else { return 0; } + } + } + else { + return 0; + } +} + +function showMode($mode, $mmdvmconfigs) +{ + // shows if mode is enabled or not. + if (getEnabled($mode, $mmdvmconfigs) == 1) { + if ($mode == "D-Star Network") { + if (isProcessRunning("ircddbgatewayd")) { + echo ""; + } else { + echo ""; + } + } + elseif ($mode == "System Fusion Network") { + if (isProcessRunning("YSFGateway")) { + echo ""; + } else { + echo ""; + } + } + elseif ($mode == "P25 Network") { + if (isProcessRunning("P25Gateway")) { + echo ""; + } else { + echo ""; + } + } + elseif ($mode == "NXDN Network") { + if (isProcessRunning("NXDNGateway")) { + echo ""; + } else { + echo ""; + } + } + elseif ($mode == "M17 Network") { + if (isProcessRunning("M17Gateway")) { + echo ""; + } else { + echo ""; + } + } + elseif ($mode == "POCSAG Network") { + if (isProcessRunning("DAPNETGateway")) { + echo ""; + } else { + echo ""; + } + } + elseif ($mode == "DMR Network") { + if (getConfigItem("DMR Network", "Address", $mmdvmconfigs) == '127.0.0.1') { + if (isProcessRunning("DMRGateway")) { + if (checkDMRLogin("DMRGateway") > 0) { echo ""; } + else { echo ""; } + } else { + echo ""; + } + } + else { + if (isProcessRunning("MMDVMHost")) { + if (checkDMRLogin("MMDVMHost") > 0) { echo ""; } + else { echo ""; } + } else { + echo ""; + } + } + } + else { + if ($mode == "D-Star" || $mode == "DMR" || $mode == "System Fusion" || $mode == "P25" || $mode == "NXDN" || $mode == "M17" || $mode == "FM" || $mode == "POCSAG") { + if (isProcessRunning("MMDVMHost")) { + echo ""; + } else { + echo ""; + } + } + } + } + elseif ( ($mode == "YSF XMode") && (getEnabled("System Fusion", $mmdvmconfigs) == 1) ) { + if ( (isProcessRunning("MMDVMHost")) && (isProcessRunning("YSF2DMR") || isProcessRunning("YSF2NXDN") || isProcessRunning("YSF2P25")) ) { + echo ""; + } else { + echo "\">"; + } + } + elseif ( ($mode == "DMR XMode") && (getEnabled("DMR", $mmdvmconfigs) == 1) ) { + if ( (isProcessRunning("MMDVMHost")) && (isProcessRunning("DMR2YSF") || isProcessRunning("DMR2NXDN")) ) { + echo ""; + } else { + echo "\">"; + } + } + elseif ( ($mode == "YSF2DMR Network") && (getEnabled("System Fusion", $mmdvmconfigs) == 1) ) { + if (isProcessRunning("YSF2DMR")) { + echo ""; + } else { + echo "\">"; + } + } + elseif ( ($mode == "YSF2NXDN Network") && (getEnabled("System Fusion", $mmdvmconfigs) == 1) ) { + if (isProcessRunning("YSF2NXDN")) { + echo ""; + } else { + echo "\">"; + } + } + elseif ( ($mode == "YSF2P25 Network") && (getEnabled("System Fusion", $mmdvmconfigs) == 1) ) { + if (isProcessRunning("YSF2P25")) { + echo ""; + } else { + echo "\">"; + } + } + elseif ( ($mode == "DMR2NXDN Network") && (getEnabled("DMR", $mmdvmconfigs) == 1) ) { + if (isProcessRunning("DMR2NXDN")) { + echo ""; + } else { + echo "\">"; + } + } + elseif ( ($mode == "DMR2YSF Network") && (getEnabled("DMR", $mmdvmconfigs) == 1) ) { + if (isProcessRunning("DMR2YSF")) { + echo ""; + } else { + echo "\">"; + } + } + else { + echo "\">"; + } + $mode = str_replace("System Fusion", "YSF", $mode); + $mode = str_replace("Network", "Net", $mode); + if (strpos($mode, 'YSF2') > -1) { $mode = str_replace(" Net", "", $mode); } + if (strpos($mode, 'DMR2') > -1) { $mode = str_replace(" Net", "", $mode); } + echo $mode."\n"; +} + +function getMMDVMLog() +{ + // Last 250 dashboard-relevant lines from today's MMDVM log, + // falling back to yesterday's tail if today is sparse (just- + // past-midnight case). The egrep|sed|tail shell pipeline that + // used to live here forked three processes per call AND + // streamed the whole day's log through them on every poll — + // see pistar_log_tail_match() for the rationale. + $logToday = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log"; + $logYstday = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; + $matchR = '/^M.*(from|end|watchdog|lost|slow data)/'; + $excR = '/(CSBK|overflow|Downlink)/'; + + $logLines1 = file_exists($logToday) + ? pistar_log_tail_match($logToday, $matchR, $excR, 250) + : array(); + $logLines2 = array(); + if (sizeof($logLines1) < 250 && file_exists($logYstday)) { + $logLines2 = pistar_log_tail_match($logYstday, $matchR, $excR, 250); + } + // Preserve the original union-by-key + final tail-slice + // semantics: today's matches take the low indices, yesterday's + // fill any higher slots up to 250 total. + $logLines = $logLines1 + $logLines2; + return array_slice($logLines, -250); +} + +function getYSFGatewayLog() +{ + // Last 1 link-state line from today's YSFGateway log, falling + // back to yesterday if today has none. + $logToday = YSFGATEWAYLOGPATH."/".YSFGATEWAYLOGPREFIX."-".gmdate("Y-m-d").".log"; + $logYstday = YSFGATEWAYLOGPATH."/".YSFGATEWAYLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; + $matchR = '/^M.*(onnection to|onnect to|inked|isconnect|Opening YSF network)/'; + $excR = '/(Linked to MMDVM|Link successful to MMDVM|\*Link)/'; + + $logLines = file_exists($logToday) + ? pistar_log_tail_match($logToday, $matchR, $excR, 1) + : array(); + if (sizeof($logLines) === 0 && file_exists($logYstday)) { + $logLines = pistar_log_tail_match($logYstday, $matchR, $excR, 1); + } + return $logLines; +} + +function getP25GatewayLog() +{ + // Last 1 link-state line from today's P25Gateway log, falling + // back to yesterday if today has none. The first space- + // delimited field (severity letter) is stripped to match the + // original `cut -d" " -f2-` step. + $logToday = P25GATEWAYLOGPATH."/".P25GATEWAYLOGPREFIX."-".gmdate("Y-m-d").".log"; + $logYstday = P25GATEWAYLOGPATH."/".P25GATEWAYLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; + $matchR = '/^M.*(ink|Starting|witched)/'; + + $logLines = file_exists($logToday) + ? pistar_log_tail_match($logToday, $matchR, '', 1, true) + : array(); + if (sizeof($logLines) === 0 && file_exists($logYstday)) { + $logLines = pistar_log_tail_match($logYstday, $matchR, '', 1, true); + } + return $logLines; +} + +function getNXDNGatewayLog() +{ + // Last 1 link-state line from today's NXDNGateway log; see + // getP25GatewayLog for the full rationale (same shape). + $logToday = "/var/log/pi-star/NXDNGateway-".gmdate("Y-m-d").".log"; + $logYstday = "/var/log/pi-star/NXDNGateway-".gmdate("Y-m-d", time() - 86340).".log"; + $matchR = '/^M.*(ink|Starting|witched)/'; + + $logLines = file_exists($logToday) + ? pistar_log_tail_match($logToday, $matchR, '', 1, true) + : array(); + if (sizeof($logLines) === 0 && file_exists($logYstday)) { + $logLines = pistar_log_tail_match($logYstday, $matchR, '', 1, true); + } + return $logLines; +} + +function getM17GatewayLog() +{ + // Last 1 link-state line from today's M17Gateway log; see + // getP25GatewayLog for the full rationale (same shape). + $logToday = "/var/log/pi-star/M17Gateway-".gmdate("Y-m-d").".log"; + $logYstday = "/var/log/pi-star/M17Gateway-".gmdate("Y-m-d", time() - 86340).".log"; + $matchR = '/^M.*(ink|Starting|witched)/'; + + $logLines = file_exists($logToday) + ? pistar_log_tail_match($logToday, $matchR, '', 1, true) + : array(); + if (sizeof($logLines) === 0 && file_exists($logYstday)) { + $logLines = pistar_log_tail_match($logYstday, $matchR, '', 1, true); + } + return $logLines; +} + +function getDAPNETGatewayLog() +{ + // Last 20 "Sending message" lines from today's DAPNETGateway + // log (or yesterday's if today is silent), reversed so the + // most recent message appears first. The original pipeline + // ended with `tail -n 20 | tac`; the helper does both. + $logToday = "/var/log/pi-star/DAPNETGateway-".gmdate("Y-m-d").".log"; + $logYstday = "/var/log/pi-star/DAPNETGateway-".gmdate("Y-m-d", time() - 86340).".log"; + $matchR = '/^M.*(Sending message)/'; + + $logLines = file_exists($logToday) + ? pistar_log_tail_match($logToday, $matchR, '', 20, true, true) + : array(); + if (sizeof($logLines) === 0 && file_exists($logYstday)) { + $logLines = pistar_log_tail_match($logYstday, $matchR, '', 20, true, true); + } + return $logLines; +} + +// 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: DVMEGA HR3.14 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_HS-ADF7021 20170414 (D-Star/DMR/YSF/P25) (Build: 20:16:25 May 20 2017) +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM 20170206 TCXO (D-Star/DMR/System Fusion/P25/RSSI/CW Id) +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: ZUMspot ADF7021 v1.0.0 20170728 (DStar/DMR/YSF/P25) GitID #c16dd5a +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_MDO ADF7021 v1.0.1 20170826 (DStar/DMR/YSF/P25) GitID #BD7KLE +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: ZUMspot-v1.0.3 20171226 ADF7021 FW by CA6JAU GitID #bfb82b4 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_HS_Hat-v1.0.3 20171226 ADF7021 FW by CA6JAU GitID #bfb82b4 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_HS-v1.0.3 20171226 ADF7021 FW by CA6JAU GitID #bfb82b4 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: MMDVM_HS_Dual_Hat-v1.3.6 20180521 dual ADF7021 FW by CA6JAU GitID #bd6217a +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: D2RG_MMDVM_HS-v1.4.17 20190529 14.7456MHz ADF7021 FW by CA6JAU GitID #cc451c4 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: Nano_hotSPOT-v1.3.3 20180224 ADF7021 FW by CA6JAU GitID #62323e7 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: Nano-Spot-v1.3.3 20180224 ADF7021 FW by CA6JAU GitID #62323e7 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: Nano_DV-v1.4.3 20180716 12.2880MHz ADF7021 FW by CA6JAU GitID #6729d23 +// I: 1970-01-01 00:00:00.000 MMDVM protocol version: 1, description: SkyBridge-v1.5.2 20201108 14.7456MHz ADF7021 FW by CA6JAU GitID #89daa20 + +function getDVModemFirmware() +{ + $logMMDVMNow = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log"; + $logMMDVMPrevious = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; + $logSearchString = "MMDVM protocol version"; + $logLine = ''; + $modemFirmware = ''; + + $logLine = exec("grep \"".$logSearchString."\" ".$logMMDVMNow." | tail -1"); + if (!$logLine) { $logLine = exec("grep \"".$logSearchString."\" ".$logMMDVMPrevious." | tail -1"); } + + if ($logLine) { + if (strpos($logLine, 'DVMEGA')) { + $modemFirmware = substr($logLine, 67, 15); + } + if (strpos($logLine, 'description: MMDVM_HS')) { + $modemFirmware = "MMDVM_HS:".ltrim(substr($logLine, 84, 8), 'v'); + } + if (strpos($logLine, 'description: MMDVM ')) { + $modemFirmware = "MMDVM:".substr($logLine, 73, 8); + } + if (strpos($logLine, 'description: ZUMspot ')) { + $modemFirmware = "ZUMspot:".strtok(substr($logLine, 83, 12), ' '); + } + if (strpos($logLine, 'description: MMDVM_MDO ')) { + $modemFirmware = "MMDVM_MDO:".ltrim(strtok(substr($logLine, 85, 12), ' '), 'v'); + } + if (strpos($logLine, 'description: ZUMspot-')) { + $modemFirmware = "ZUMspot:".strtok(substr($logLine, 75, 12), ' '); + } + if (strpos($logLine, 'description: MMDVM_HS_Hat-')) { + $modemFirmware = "HS_Hat:".strtok(substr($logLine, 80, 12), ' '); + } + if (strpos($logLine, 'description: MMDVM_HS_Dual_Hat-')) { + $modemFirmware = "HS_Hat:".strtok(substr($logLine, 85, 12), ' '); + } + if (strpos($logLine, 'description: D2RG_MMDVM_HS-')) { + $modemFirmware = "HS_Hat:".strtok(substr($logLine, 81, 12), ' '); + } + if (strpos($logLine, 'description: MMDVM_HS-')) { + $modemFirmware = "MMDVM_HS:".ltrim(strtok(substr($logLine, 76, 12), ' '), 'v'); + } + if (strpos($logLine, 'description: Nano_hotSPOT-')) { + $modemFirmware = "MMDVM_HS:".ltrim(strtok(substr($logLine, 80, 12), ' '), 'v'); + } + if (strpos($logLine, 'description: Nano-Spot-')) { + $modemFirmware = "NanoSpot:".strtok(substr($logLine, 77, 12), ' '); + } + if (strpos($logLine, 'description: Nano_DV-')) { + $modemFirmware = "NanoDV:".strtok(substr($logLine, 75, 12), ' '); + } + if (strpos($logLine, 'description: OpenGD77 Hotspot')) { + $modemFirmware = "OpenGD77:".strtok(substr($logLine, 83, 12), ' '); + } + if (strpos($logLine, 'description: OpenGD77_HS ')) { + $modemFirmware = "OpenGD77:".strtok(substr($logLine, 79, 12), ' '); + } + if (strpos($logLine, 'description: SkyBridge-')) { + $modemFirmware = "SkyBrg:".strtok(substr($logLine, 77, 12), ' '); + } + } + return $modemFirmware; +} + +function getDVModemTCXOFreq() +{ + $logMMDVMNow = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d").".log"; + $logMMDVMPrevious = MMDVMLOGPATH."/".MMDVMLOGPREFIX."-".gmdate("Y-m-d", time() - 86340).".log"; + $logSearchString = "MMDVM protocol version"; + $logLine = ''; + $modemTCXOFreq = ''; + + $logLine = exec("grep \"".$logSearchString."\" ".$logMMDVMNow." | tail -1"); + if (!$logLine) { $logLine = exec("grep \"".$logSearchString."\" ".$logMMDVMPrevious." | tail -1"); } + + if ($logLine) { + if ((strpos($logLine, 'Mhz') !== false) or (strpos($logLine, 'MHz') !== false)) { + $modemTCXOFreq = $logLine; + $modemTCXOFreq = preg_replace('/.*(\d{2}\.\d{3,4}\s{0,1}M[Hh]z).*/', "$1", $modemTCXOFreq); + $modemTCXOFreq = str_replace("MHz"," MHz", $modemTCXOFreq); + } + } + return $modemTCXOFreq; +} + +// 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 +// M: 2000-00-00 00:00:00.000 Mode set to D-Star +// M: 2000-00-00 00:00:00.000 D-Star, received RF header from M1ABC /ABCD to CQCQCQ +// M: 2000-00-00 00:00:00.000 D-Star, received RF end of transmission from M1ABC /ABCD to CQCQCQ , 00.0 seconds, BER: 0.0%, RSSI: -43/-43/-43 dBm +// M: 2000-00-00 00:00:00.000 D-Star, received network header from M1ABC /ABCD to CQCQCQ via REF000 A +// M: 2000-00-00 00:00:00.000 D-Star, received network end of transmission from M1ABC /ABCD to CQCQCQ , 0.0 seconds, 0% packet loss, BER: 0.0% +// M: 2000-00-00 00:00:00.000 D-Star, starting fast data mode +// M: 2000-00-00 00:00:00.000 D-Star, leaving fast data mode +// M: 2000-00-00 00:00:00.000 D-Star, invalid slow data header +// M: 2000-00-00 00:00:00.000 DMR Slot 2, received network voice header from M1ABC to TG 1 +// M: 2000-00-00 00:00:00.000 DMR Slot 2, received RF voice header from M1ABC to 5000 +// M: 2000-00-00 00:00:00.000 DMR Slot 2, received RF end of voice transmission, 1.8 seconds, BER: 3.9% +// M: 2000-00-00 00:00:00.000 DMR Slot 2, received network end of voice transmission from M1ABC to TG 2, 0.0 seconds, 0% packet loss, BER: 0.0% +// M: 2000-00-00 00:00:00.000 DMR Slot 2, RF voice transmission lost, 1.1 seconds, BER: 6.5% +// M: 2000-00-00 00:00:00.000 DMR Slot 2, received RF CSBK Preamble CSBK (1 to follow) from M1ABC to TG 1 +// M: 2000-00-00 00:00:00.000 DMR Slot 2, received network Data Preamble VSBK (11 to follow) from 123456 to TG 123456 +// M: 2000-00-00 00:00:00.000 DMR Talker Alias (Data Format 1, Received 24/24 char): 'Hide the bottle from Ont' +// M: 2000-00-00 00:00:00.000 0000: 07 00 20 4F 6E 74 00 00 00 *.. Ont...* +// M: 2000-00-00 00:00:00.000 DMR Slot 2, Embedded Talker Alias Block 3 +// M: 2000-00-00 00:00:00.000 DMR Slot 2, received network data header from 123999 to M1ABC, 0 blocks +// M: 2000-00-00 00:00:00.000 DMR Slot 2, ended network data transmission from 123999 to M1ABC +// M: 2000-00-00 00:00:00.000 P25, received RF transmission from M1ABC to TG 10200 +// M: 2000-00-00 00:00:00.000 Debug: P25RX: pos/neg/centre/threshold 106 -105 0 106 +// M: 2000-00-00 00:00:00.000 Debug: P25RX: sync found in Ldu pos/centre/threshold 3986 9 104 +// M: 2000-00-00 00:00:00.000 Debug: P25RX: pos/neg/centre/threshold 267 -222 22 245 +// M: 2000-00-00 00:00:00.000 Debug: P25RX: sync found in Ldu pos/centre/threshold 3986 10 112 +// M: 2000-00-00 00:00:00.000 P25, received RF end of transmission, 0.4 seconds, BER: 0.0% +// M: 2000-00-00 00:00:00.000 P25, received network transmission from 10999 to TG 10200 +// M: 2000-00-00 00:00:00.000 P25, network end of transmission, 1.8 seconds, 0% packet loss +// M: 2000-00-00 00:00:00.000 YSF, received RF data from MW0MWZ to ALL +// M: 2000-00-00 00:00:00.000 YSF, received RF end of transmission, 5.1 seconds, BER: 3.8% +// M: 2000-00-00 00:00:00.000 YSF, received network data from M1ABC to ALL at MB6IBK +// M: 2000-00-00 00:00:00.000 YSF, network watchdog has expired, 5.0 seconds, 0% packet loss, BER: 0.0% +// M: 2000-00-00 00:00:00.000 NXDN, received RF transmission from MW0MWZ to TG 65000 +// M: 2000-00-00 00:00:00.000 Debug: NXDNRX: pos/neg/centre/threshold 106 -105 0 106 +// M: 2000-00-00 00:00:00.000 Debug: NXDNRX: sync found in Ldu pos/centre/threshold 3986 9 104 +// M: 2000-00-00 00:00:00.000 Debug: NXDNRX: pos/neg/centre/threshold 267 -222 22 245 +// M: 2000-00-00 00:00:00.000 Debug: NXDNRX: sync found in Ldu pos/centre/threshold 3986 10 112 +// M: 2000-00-00 00:00:00.000 NXDN, received RF end of transmission, 0.4 seconds, BER: 0.0% +// M: 2000-00-00 00:00:00.000 NXDN, received network transmission from 10999 to TG 65000 +// M: 2000-00-00 00:00:00.000 NXDN, network end of transmission, 1.8 seconds, 0% packet loss +// M: 2000-00-00 00:00:00.000 M17, received RF late entry voice transmission from M1ABC to INFO +// M: 2000-00-00 00:00:00.000 M17, received RF end of transmission from M1ABC to INFO, 2.1 seconds, BER: 0.2%, RSSI: -60/-60/-60 dBm +// M: 2000-00-00 00:00:00.000 M17, received network voice transmission from M1ABC to ECHO +// M: 2000-00-00 00:00:00.000 M17, received network end of transmission from M1ABC to ECHO, 0.0 seconds +// M: 2000-00-00 00:00:00.000 POCSAG, transmitted 1 frame(s) of data from 1 message(s) +// M: 2000-00-00 00:00:00.000 Mode set to Idle +function getHeardList($logLines) +{ + //array_multisort($logLines,SORT_DESC); + $heardList = array(); + $ts1duration = ""; + $ts1loss = ""; + $ts1ber = ""; + $ts1rssi = ""; + $ts2duration = ""; + $ts2loss = ""; + $ts2ber = ""; + $ts2rssi = ""; + $dstarduration = ""; + $dstarloss = ""; + $dstarber = ""; + $dstarrssi = ""; + $ysfduration = ""; + $ysfloss = ""; + $ysfber = ""; + $ysfrssi = ""; + $p25duration = ""; + $p25loss = ""; + $p25ber = ""; + $p25rssi = ""; + $nxdnduration = ""; + $nxdnloss = ""; + $nxdnber = ""; + $nxdnrssi = ""; + $pocsagduration = ""; + foreach ($logLines as $logLine) { + $duration = ""; + $loss = ""; + $ber = ""; + $rssi = ""; + //removing invalid lines + if(strpos($logLine,"BS_Dwn_Act")) { + continue; + } else if(strpos($logLine,"invalid access")) { + continue; + } else if(strpos($logLine,"received RF header for wrong repeater")) { + continue; + } else if(strpos($logLine,"unable to decode the network CSBK")) { + continue; + } else if(strpos($logLine,"overflow in the DMR slot RF queue")) { + continue; + } else if(strpos($logLine,"overflow in the M17 RF queue")) { + continue; + } else if(strpos($logLine,"non repeater RF header received")) { + continue; + } else if(strpos($logLine,"Embedded Talker Alias")) { + continue; + } else if(strpos($logLine,"DMR Talker Alias")) { + continue; + } else if(strpos($logLine,", Talker Alias ")) { + continue; + } else if(strpos($logLine,", text Data: ")) { + continue; + } else if(strpos($logLine,"CSBK Preamble")) { + continue; + } else if(strpos($logLine,"Preamble CSBK")) { + continue; + } + + if(strpos($logLine, "end of") || strpos($logLine, "watchdog has expired") || strpos($logLine, "invalid slow data header") || strpos($logLine, "ended RF data") || strpos($logLine, "d network data") || strpos($logLine, "RF user has timed out") || strpos($logLine, "transmission lost") || strpos($logLine, "POCSAG")) { + $lineTokens = explode(", ",$logLine); + if (array_key_exists(2,$lineTokens)) { + $duration = strtok($lineTokens[2], " "); + } + if (array_key_exists(3,$lineTokens)) { + $loss = $lineTokens[3]; + } + // The change to this code was causing all FCS traffic to always show TOut rather than the timer. + // This version should still show time-out when needed, AND show the time if it exists. + if (strpos($logLine,"RF user has timed out") || strpos($logLine,"watchdog has expired") || strpos($logLine, "invalid slow data header")) { + if (array_key_exists(2,$lineTokens) && strpos($lineTokens[2], "seconds")) { + $duration = strtok($lineTokens[2], " "); + } else { + $duration = "TOut"; + } + $ber = "??%"; + } + + // if RF-Packet with no BER reported (e.g. YSF Wires-X commands) then RSSI is in LOSS position + if (startsWith($loss,"RSSI")) { + $lineTokens[4] = $loss; //move RSSI to the position expected on code below + $loss = 'BER: ??%'; + } + + // if RF-Packet, no LOSS would be reported, so BER is in LOSS position + if (startsWith($loss,"BER")) { + $ber = substr($loss, 5); + $loss = "0%"; + if (array_key_exists(4,$lineTokens) && startsWith($lineTokens[4],"RSSI")) { + $rssi = substr($lineTokens[4], 6); + $dBraw = substr($rssi, strrpos($rssi,'/')+1); //average only + $relint = intval($dBraw) + 93; + $signal = round(($relint/6)+9, 0); + if ($signal < 0) $signal = 0; + if ($signal > 9) $signal = 9; + if ($relint > 0) { + $rssi = "S{$signal}+{$relint}dB ({$dBraw})"; + } else { + $rssi = "S{$signal} ({$dBraw})"; + } + } + } else { + $loss = strtok($loss, " "); + if (array_key_exists(4,$lineTokens)) { + $ber = substr($lineTokens[4], 5); + } + } + + if (strpos($logLine,"ended RF data") || strpos($logLine,"d network data")) { + switch (substr($logLine, 27, strpos($logLine,",") - 27)) { + case "DMR Slot 1": + $ts1duration = "DMR Data"; + break; + case "DMR Slot 2": + $ts2duration = "DMR Data"; + break; + } + } else { + switch (substr($logLine, 27, strpos($logLine,",") - 27)) { + case "D-Star": + $dstarduration = $duration; + $dstarloss = $loss; + $dstarber = $ber; + $dstarrssi = $rssi; + break; + case "DMR Slot 1": + $ts1duration = $duration; + $ts1loss = $loss; + $ts1ber = $ber; + $ts1rssi = $rssi; + break; + case "DMR Slot 2": + $ts2duration = $duration; + $ts2loss = $loss; + $ts2ber = $ber; + $ts2rssi = $rssi; + break; + case "YSF": + $ysfduration = $duration; + $ysfloss = $loss; + $ysfber = $ber; + $ysfrssi = $rssi; + break; + case "P25": + $p25duration = $duration; + $p25loss = $loss; + $p25ber = $ber; + $p25rssi = $rssi; + break; + case "NXDN": + $nxdnduration = $duration; + $nxdnloss = $loss; + $nxdnber = $ber; + $nxdnrssi = $rssi; + break; + case "M17": + $m17duration = $duration; + $m17loss = $loss; + $m17ber = $ber; + $m17rssi = $rssi; + break; + case "POCSAG": + $pocsagduration = "POCSAG Data"; + break; + } + } + } + + $timestamp = substr($logLine, 3, 19); + $mode = substr($logLine, 27, strpos($logLine,",") - 27); + $callsign2 = substr($logLine, strpos($logLine,"from") + 5, strpos($logLine,"to") - strpos($logLine,"from") - 6); + $callsign = $callsign2; + if (strpos($callsign2,"/") > 0) { + $callsign = substr($callsign2, 0, strpos($callsign2,"/")); + } + $callsign = trim($callsign); + + $id =""; + if ($mode == "D-Star") { + $id = substr($callsign2, strpos($callsign2,"/") + 1); + } + + $target = trim(substr($logLine, strpos($logLine, "to") + 3)); + // Handle more verbose logging from MMDVMHost + if (strpos($target,",") !== 'false') { $target = explode(",", $target)[0]; } + + $source = "RF"; + if (strpos($logLine,"network") > 0 || strpos($logLine,"POCSAG") > 0) { + $source = "Net"; + } + + switch ($mode) { + case "D-Star": + $duration = $dstarduration; + $loss = $dstarloss; + $ber = $dstarber; + $rssi = $dstarrssi; + break; + case "DMR Slot 1": + $duration = $ts1duration; + $loss = $ts1loss; + $ber = $ts1ber; + $rssi = $ts1rssi; + break; + case "DMR Slot 2": + $duration = $ts2duration; + $loss = $ts2loss; + $ber = $ts2ber; + $rssi = $ts2rssi; + break; + case "YSF": + $duration = $ysfduration; + $loss = $ysfloss; + $ber = $ysfber; + $rssi = $ysfrssi; + $target = preg_replace('!\s+!', ' ', $target); + break; + case "P25": + if ($source == "Net" && $target == "TG 10") {$callsign = "PARROT";} + if ($source == "Net" && $callsign == "10999") {$callsign = "MMDVM";} + $duration = $p25duration; + $loss = $p25loss; + $ber = $p25ber; + $rssi = $p25rssi; + break; + case "NXDN": + if ($source == "Net" && $target == "TG 10") {$callsign = "PARROT";} + $duration = $nxdnduration; + $loss = $nxdnloss; + $ber = $nxdnber; + $rssi = $nxdnrssi; + break; + case "M17": + $duration = $m17duration; + $loss = $m17loss; + $ber = $m17ber; + $rssi = $m17rssi; + break; + case "POCSAG": + $callsign = "DAPNET"; + $target = "DAPNET User"; + $duration = "POCSAG Data"; + break; + } + + // Callsign or ID should be less than 11 chars long, otherwise it could be errorneous + if ( strlen($callsign) < 11 ) { + array_push($heardList, array($timestamp, $mode, $callsign, $id, $target, $source, $duration, $loss, $ber, $rssi)); + $duration = ""; + $loss =""; + $ber = ""; + $rssi = ""; + } + } + return $heardList; +} + +function getLastHeard($logLines) +{ + //returns last heard list from log + $lastHeard = array(); + $heardCalls = array(); + $heardList = getHeardList($logLines); + $counter = 0; + foreach ($heardList as $listElem) { + if ( ($listElem[1] == "D-Star") || ($listElem[1] == "YSF") || ($listElem[1] == "P25") || ($listElem[1] == "NXDN") || ($listElem[1] == "M17") || ($listElem[1] == "POCSAG") || (startsWith($listElem[1], "DMR")) ) { + $callUuid = $listElem[2]."#".$listElem[1].$listElem[3].$listElem[5]; + if(!(array_search($callUuid, $heardCalls) > -1)) { + array_push($heardCalls, $callUuid); + array_push($lastHeard, $listElem); + $counter++; + } + } + } + return $lastHeard; +} + +function getActualMode($metaLastHeard, $mmdvmconfigs) +{ + // returns mode of repeater actual working in + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $listElem = $metaLastHeard[0]; + $timestamp = new DateTime($listElem[0], $utc_tz); + $timestamp->setTimeZone($local_tz); + $mode = $listElem[1]; + if (startsWith($mode, "DMR")) { + $mode = "DMR"; + } + + $now = new DateTime(); + $hangtime = getConfigItem("General", "ModeHang", $mmdvmconfigs); + + if ($hangtime != "") { + $timestamp->add(new DateInterval('PT' . $hangtime . 'S')); + } else { + $source = $listElem[5]; + if ($source == "RF" && $mode === "D-Star") { + $hangtime = getConfigItem("D-Star", "ModeHang", $mmdvmconfigs); + } + else if ($source == "Net" && $mode === "D-Star") { + $hangtime = getConfigItem("D-Star Network", "ModeHang", $mmdvmconfigs); + } + else if ($source == "RF" && $mode === "DMR") { + $hangtime = getConfigItem("DMR", "ModeHang", $mmdvmconfigs); + } + else if ($source == "Net" && $mode === "DMR") { + $hangtime = getConfigItem("DMR Network", "ModeHang", $mmdvmconfigs); + } + else if ($source == "RF" && $mode === "YSF") { + $hangtime = getConfigItem("System Fusion", "ModeHang", $mmdvmconfigs); + } + else if ($source == "Net" && $mode === "YSF") { + $hangtime = getConfigItem("System Fusion Network", "ModeHang", $mmdvmconfigs); + } + else if ($source == "RF" && $mode === "P25") { + $hangtime = getConfigItem("P25", "ModeHang", $mmdvmconfigs); + } + else if ($source == "Net" && $mode === "P25") { + $hangtime = getConfigItem("P25 Network", "ModeHang", $mmdvmconfigs); + } + else if ($source == "RF" && $mode === "NXDN") { + $hangtime = getConfigItem("NXDN", "ModeHang", $mmdvmconfigs); + } + else if ($source == "Net" && $mode === "NXDN") { + $hangtime = getConfigItem("NXDN Network", "ModeHang", $mmdvmconfigs); + } + else if ($source == "RF" && $mode === "M17") { + $hangtime = getConfigItem("M17", "ModeHang", $mmdvmconfigs); + } + else if ($source == "Net" && $mode === "M17") { + $hangtime = getConfigItem("M17 Network", "ModeHang", $mmdvmconfigs); + } + else if ($source == "RF" && $mode === "FM") { + $hangtime = getConfigItem("FM", "ModeHang", $mmdvmconfigs); + } + else if ($source == "Net" && $mode === "FM") { + $hangtime = getConfigItem("FM Network", "ModeHang", $mmdvmconfigs); + } + else if ($source == "Net" && $mode === "POCSAG") { + $hangtime = getConfigItem("POCSAG Network", "ModeHang", $mmdvmconfigs); + } + else { + $hangtime = getConfigItem("General", "RFModeHang", $mmdvmconfigs); + } + $timestamp->add(new DateInterval('PT' . $hangtime . 'S')); + } + if ($listElem[6] != null) { //if terminated, hangtime counts after end of transmission + $seconds = is_numeric($listElem[6]) ? ceil((float)$listElem[6]) : 0; + $timestamp->add(new DateInterval('PT' . $seconds . 'S')); + //$timestamp->add(new DateInterval('PT' . ceil($listElem[6]) . 'S')); + } else { //if not terminated, always return mode + return $mode; + } + if ($now->format('U') > $timestamp->format('U')) { + return "idle"; + } else { + return $mode; + } +} + +function getDSTARLinks() +{ + // Get our current configured callsign / module + $mmdvmconfigs = getMMDVMConfig(); + $dstarCallsign = str_pad(getConfigItem("General", "Callsign", $mmdvmconfigs), 7, " ", STR_PAD_RIGHT).getConfigItem("D-Star", "Module", $mmdvmconfigs); + + // returns link-states of all D-Star-modules + if (filesize(LINKLOGPATH."/Links.log") == 0) { + return "Not Linked"; + } + if ($linkLog = fopen(LINKLOGPATH."/Links.log",'r')) { + while ($linkLine = fgets($linkLog)) { + $linkDate = " "; + $protocol = " "; + $linkType = " "; + $linkSource = " "; + $linkDest = " "; + $linkDir = " "; +// Reflector-Link, sample: +// 2011-09-22 02:15:06: DExtra link - Type: Repeater Rptr: DB0LJ B Refl: XRF023 A Dir: Outgoing +// 2012-04-03 08:40:07: DPlus link - Type: Dongle Rptr: DB0ERK B Refl: REF006 D Dir: Outgoing +// 2012-04-03 08:40:07: DCS link - Type: Repeater Rptr: DB0ERK C Refl: DCS001 C Dir: Outgoing + if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*Rptr: (.{8}).*Refl: (.{8}).*Dir: (.{8})/',$linkLine,$linx) > 0){ + $linkDate = $linx[1][0]; + $protocol = $linx[2][0]; + $linkType = $linx[3][0]; + $linkSource = $linx[4][0]; + $linkDest = $linx[5][0]; + $linkDir = $linx[6][0]; + if ($linkSource != $dstarCallsign) { + $linkDate = " "; + $protocol = " "; + $linkType = " "; + $linkSource = " "; + $linkDest = " "; + $linkDir = " "; + } + } +// CCS-Link, sample: +// 2013-03-30 23:21:53: CCS link - Rptr: PE1AGO C Remote: PE1KZU Dir: Incoming + if(preg_match_all('/^(.{19}).*(CC[A-Za-z]*).*Rptr: (.{8}).*Remote: (.{8}).*Dir: (.{8})/',$linkLine,$linx) > 0){ + $linkDate = $linx[1][0]; + $protocol = $linx[2][0]; + $linkType = $linx[2][0]; + $linkSource = $linx[3][0]; + $linkDest = $linx[4][0]; + $linkDir = $linx[5][0]; + } +// Dongle-Link, sample: +// 2011-09-24 07:26:59: DPlus link - Type: Dongle User: DC1PIA Dir: Incoming +// 2012-03-14 21:32:18: DPlus link - Type: Dongle User: DC1PIA Dir: Incoming + if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*User: (.{6,8}).*Dir: (.*)$/',$linkLine,$linx) > 0){ + $linkDate = $linx[1][0]; + $protocol = $linx[2][0]; + $linkType = $linx[3][0]; + $linkSource = " "; + $linkDest = $linx[4][0]; + $linkDir = $linx[5][0]; + } + if (strtolower(substr($linkDir, 0, 2)) == "in") { $linkDir = "In"; } + if (strtolower(substr($linkDir, 0, 3)) == "out") { $linkDir = "Out"; } + $out = $linkDest." ".$protocol."/".$linkDir; + } + } + fclose($linkLog); + return $out; +} + +function getActualLink($logLines, $mode) +{ + // returns actual link state of specific mode + //M: 2016-05-02 07:04:10.504 D-Star link status set to "Verlinkt zu DCS002 S" + //M: 2016-04-03 16:16:18.638 DMR Slot 2, received network voice header from 4000 to 2625094 + //M: 2016-04-03 19:30:03.099 DMR Slot 2, received network voice header from 4020 to 2625094 + //M: 2017-09-03 08:10:42.862 DMR Slot 2, received network data header from M6JQD to TG 9, 5 blocks + switch ($mode) { + case "D-Star": + if (isProcessRunning(IRCDDBGATEWAY)) { + return getDSTARLinks(); + } else { + return "No D-Star Network"; + } + break; + case "DMR Slot 1": + foreach ($logLines as $logLine) { + if(strpos($logLine,"unable to decode the network CSBK")) { + continue; + } else if(substr($logLine, 27, strpos($logLine,",") - 27) == "DMR Slot 1") { + $to = ""; + if (strpos($logLine,"to")) { + $to = trim(substr($logLine, strpos($logLine,"to") + 3)); + } + if ($to !== "") { + if (substr($to, 0, 3) !== 'TG ') { + continue; + } + if ($to === "TG 4000") { + return "No TG"; + } + if (strpos($to, ',') !== false) { + $to = substr($to, 0, strpos($to, ',')); + } + return $to; + } + } + } + return "No TG"; + break; + case "DMR Slot 2": + foreach ($logLines as $logLine) { + if(strpos($logLine,"unable to decode the network CSBK")) { + continue; + } else if(substr($logLine, 27, strpos($logLine,",") - 27) == "DMR Slot 2") { + $to = ""; + if (strpos($logLine,"to")) { + $to = trim(substr($logLine, strpos($logLine,"to") + 3)); + } + if ($to !== "") { + if (substr($to, 0, 3) !== 'TG ') { + continue; + } + if ($to === "TG 4000") { + return "No TG"; + } + if (strpos($to, ',') !== false) { + $to = substr($to, 0, strpos($to, ',')); + } + return $to; + } + } + } + return "No TG"; + break; + + case "YSF": + // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 + // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + // M: 0000-00-00 00:00:00.000 Connect to 62829 has been requested by M1ABC + // M: 0000-00-00 00:00:00.000 Automatic connection to 62829 + // New YSFGateway Format + // M: 0000-00-00 00:00:00.000 Opening YSF network connection + // M: 0000-00-00 00:00:00.000 Automatic (re-)connection to 16710 - "GB SOUTH WEST " + // M: 0000-00-00 00:00:00.000 Automatic (re-)connection to FCS00290 + // M: 0000-00-00 00:00:00.000 Linked to GB SOUTH WEST + // M: 0000-00-00 00:00:00.000 Linked to FCS002-90 + // M: 0000-00-00 00:00:00.000 Disconnect via DTMF has been requested by M1ABC + // M: 0000-00-00 00:00:00.000 Connect to 00003 - "YSF2NXDN " has been requested by M1ABC + // M: 0000-00-00 00:00:00.000 Link has failed, polls lost + + if (isProcessRunning("YSFGateway")) { + $to = ""; + foreach($logLines as $logLine) { + if ( (strpos($logLine,"Linked to")) && (!strpos($logLine,"Linked to MMDVM")) ) { + $to = trim(substr($logLine, 37, 16)); + if (substr($to, 0, 3) === "FCS") { $to = str_replace(' ', '', str_replace('-', '', $to)); } + } + if (strpos($logLine,"Automatic (re-)connection to")) { + if (strpos($logLine,"Automatic (re-)connection to FCS")) { + $to = substr($logLine, 56, 8); + } + else { + $to = substr($logLine, 56, 5); + } + } + if (strpos($logLine,"Connect to")) { + $to = substr($logLine, 38, 5); + } + if (strpos($logLine,"Automatic connection to")) { + $to = substr($logLine, 51, 5); + } + if (strpos($logLine,"Disconnect via DTMF")) { + $to = "Not Linked"; + } + if (strpos($logLine,"Opening YSF network connection")) { + $to = "Not Linked"; + } + if (strpos($logLine,"Link has failed")) { + $to = "Not Linked"; + } + if (strpos($logLine,"DISCONNECT Reply")) { + $to = "Not Linked"; + } + if ($to !== "") { + return $to; + } + } + return "Not Linked"; + } else { + return "Service Not Started"; + } + break; + + case "NXDN": + // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 + // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + // 2000-01-01 00:00:00.000 Linked at startup to reflector 10100 + // 2000-01-01 00:00:00.000 Unlinked from reflector 10100 by M1ABC + // 2000-01-01 00:00:00.000 Linked to reflector 10100 by M1ABC + // 2000-01-01 00:00:00.000 No response from 10200, unlinking + // 2000-01-01 00:00:00.000 Switched to reflector 10100 by remote command + // 2000-01-01 00:00:00.000 Unlinking from 10100 due to inactivity + // 2000-01-01 00:00:00.000 Statically linked to reflector 10100 + if (isProcessRunning("NXDNGateway")) { + foreach($logLines as $logLine) { + $to = ""; + if (strpos($logLine,"Linked to")) { + $to = preg_replace('/[^0-9]/', '', substr($logLine, 44, 5)); + $to = preg_replace('/[^0-9]/', '', $to); + return "TG ".$to; + } + if (strpos($logLine,"Linked at start")) { + $to = preg_replace('/[^0-9]/', '', substr($logLine, 55, 5)); + $to = preg_replace('/[^0-9]/', '', $to); + return "TG ".$to; + } + if (strpos($logLine,"Statically linked to reflector")) { + $to = preg_replace('/[^0-9]/', '', substr($logLine, 55, 5)); + $to = preg_replace('/[^0-9]/', '', $to); + return "TG ".$to; + } + if (strpos($logLine,"Switched to reflector")) { + $to = preg_replace('/[^0-9]/', '', substr($logLine, 46, 5)); + $to = preg_replace('/[^0-9]/', '', $to); + return "TG ".$to; + } + if (strpos($logLine,"Starting NXDNGateway")) { + return "Not Linked"; + } + if (strpos($logLine,"unlinking")) { + return "Not Linked"; + } + if (strpos($logLine,"Unlinked from")) { + return "Not Linked"; + } + if (strpos($logLine,"Unlinking from")) { + return "Not Linked"; + } + } + return "Not Linked"; + } else { + return "Service Not Started"; + } + break; + + case "M17": + // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 + // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + if (isProcessRunning("M17Gateway")) { + foreach($logLines as $logLine) { + if(preg_match_all('/Linked .* reflector (M17-.{3} [A-Z])/',$logLine,$linx) > 0){ + return $linx[1][0]; + } + if (strpos($logLine,"Starting M17Gateway")) { + return "Not Linked"; + } + if (strpos($logLine,"unlinking")) { + return "Not Linked"; + } + if (strpos($logLine,"Unlinking")) { + return "Not Linked"; + } + if (strpos($logLine,"Unlinked")) { + return "Not Linked"; + } + } + return "Not Linked"; + } else { + return "Service Not Started"; + } + break; + + case "P25": + // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 + // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + // 2000-01-01 00:00:00.000 Linked at startup to reflector 10100 + // 2000-01-01 00:00:00.000 Unlinked from reflector 10100 by M1ABC + // 2000-01-01 00:00:00.000 Linked to reflector 10100 by M1ABC + // 2000-01-01 00:00:00.000 No response from 10100, unlinking + // 2000-01-01 00:00:00.000 Switched to reflector 10100 due to RF activity from 12345 + // 2000-01-01 00:00:00.000 Unlinking from reflector 10100 by 12345 + // 2000-01-01 00:00:00.000 Switched to reflector 10100 by remote command + if (isProcessRunning("P25Gateway")) { + foreach($logLines as $logLine) { + $to = ""; + if (strpos($logLine,"Linked to")) { + $to = preg_replace('/[^0-9]/', '', substr($logLine, 44, 5)); + $to = preg_replace('/[^0-9]/', '', $to); + return "TG ".$to; + } + if (strpos($logLine,"Linked at startup to")) { + $to = preg_replace('/[^0-9]/', '', substr($logLine, 55, 5)); + $to = preg_replace('/[^0-9]/', '', $to); + return "TG ".$to; + } + if (strpos($logLine,"Statically linked to reflector")) { + $to = preg_replace('/[^0-9]/', '', substr($logLine, 55, 5)); + $to = preg_replace('/[^0-9]/', '', $to); + return "TG ".$to; + } + if (strpos($logLine,"Switched to reflector")) { + $to = preg_replace('/[^0-9]/', '', substr($logLine, 46, 5)); + $to = preg_replace('/[^0-9]/', '', $to); + return "TG ".$to; + } + if (strpos($logLine,"Starting P25Gateway")) { + return "Not Linked"; + } + if (strpos($logLine,"unlinking")) { + return "Not Linked"; + } + if (strpos($logLine,"Unlinking")) { + return "Not Linked"; + } + if (strpos($logLine,"Unlinked")) { + return "Not Linked"; + } + } + return "Not Linked"; + } else { + return "Service Not Started"; + } + break; + } + return "Service Not Started"; +} + +function getActualReflector($logLines, $mode) +{ + // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 + // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 + // M: 2016-05-02 07:04:10.504 D-Star link status set to "Verlinkt zu DCS002 S" + // M: 2016-04-03 16:16:18.638 DMR Slot 2, received network voice header from 4000 to 2625094 + // M: 2016-04-03 19:30:03.099 DMR Slot 2, received network voice header from 4020 to 2625094 + foreach ($logLines as $logLine) { + if (substr($logLine, 27, strpos($logLine,",") - 27) == $mode) { + $from = substr($logLine, strpos($logLine,"from") + 5, strpos($logLine,"to") - strpos($logLine,"from") - 6); + if (strlen($from) == 4 && startsWith($from,"4")) { + if ($from == "4000") { + return "No Ref"; + } else { + return "Ref ".$from; + } + } + } + } + return "No Ref"; +} + +//Some basic inits +$mmdvmconfigs = getMMDVMConfig(); +if (!in_array($_SERVER["PHP_SELF"],array('/mmdvmhost/bm_links.php','/mmdvmhost/bm_manager.php'),true)) { + $logLinesMMDVM = getMMDVMLog(); + $reverseLogLinesMMDVM = $logLinesMMDVM; + array_multisort($reverseLogLinesMMDVM,SORT_DESC); + $lastHeard = getLastHeard($reverseLogLinesMMDVM); + + // Only need these in repeaterinfo.php + if (strpos($_SERVER["PHP_SELF"], 'repeaterinfo.php') !== false || strpos($_SERVER["PHP_SELF"], 'index.php') !== false) { + $logLinesYSFGateway = getYSFGatewayLog(); + $reverseLogLinesYSFGateway = $logLinesYSFGateway; + array_multisort($reverseLogLinesYSFGateway,SORT_DESC); + $logLinesP25Gateway = getP25GatewayLog(); + $logLinesNXDNGateway = getNXDNGatewayLog(); + $logLinesM17Gateway = getM17GatewayLog(); + } + // Only need these in index.php + if (strpos($_SERVER["PHP_SELF"], 'index.php') !== false || strpos($_SERVER["PHP_SELF"], 'pages.php') !== false) { + $logLinesDAPNETGateway = getDAPNETGatewayLog(); + } +} diff --git a/admin/mmdvmhost/index.php b/admin/mmdvmhost/index.php new file mode 100644 index 0000000..e69de29 diff --git a/admin/mmdvmhost/lh.php b/admin/mmdvmhost/lh.php new file mode 100644 index 0000000..cb6babd --- /dev/null +++ b/admin/mmdvmhost/lh.php @@ -0,0 +1,201 @@ + + + + + + + + + + + + + +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 zoneTransmitted ModeCallsignTarget, D-Star Reflector, DMR Talk Group etcReceived from source(s)Duration in SecondsPacket LossBit Error Rate
$local_time$modeHtml$cs$cs$cs
$csTrimHtml/$csSuffix
(GPS)
(GPS)
$tgtHtml".str_replace(' ', ' ', $tgtHtml)."RF$srcTX " . $duration_string . " secDMR DataPOCSAG Data$dur$loss$loss$loss$loss$ber$ber$ber$ber
+ + + diff --git a/admin/mmdvmhost/localtx.php b/admin/mmdvmhost/localtx.php new file mode 100644 index 0000000..3560046 --- /dev/null +++ b/admin/mmdvmhost/localtx.php @@ -0,0 +1,108 @@ + + + + + + + + + + + + + +setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + 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 { + if (strpos($listElem[2],"-") > 0) { $listElem[2] = substr($listElem[2], 0, strpos($listElem[2],"-")); } + if ($listElem[3] && $listElem[3] != ' ' ) { + echo ""; + } else { + echo ""; + } + } + if (strlen($listElem[4]) == 1) { $listElem[4] = str_pad($listElem[4], 8, " ", STR_PAD_LEFT); } + 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 { + echo""; //duration + + // 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""; //rssi + } + echo "\n"; + $counter++; } + } + } + +?> +
()Time in time zoneTransmitted ModeCallsignTarget, D-Star Reflector, DMR Talk Group etcReceived from source(s)Duration in SecondsBit Error RateRSSIReceived Signal Strength Indication
$local_time".str_replace('Slot ', 'TS', $listElem[1])."$listElem[2]".$listElem[2]."$listElem[2]
$listElem[2]/$listElem[3]
(GPS)
(GPS)
".str_replace(" "," ", $listElem[4])."RF$listElem[5]TX " . $duration_string . " secDMR Data$listElem[6]$listElem[8]$listElem[8]$listElem[8]$listElem[8]$listElem[9]
diff --git a/admin/mmdvmhost/m17_manager.php b/admin/mmdvmhost/m17_manager.php new file mode 100644 index 0000000..ea25bd4 --- /dev/null +++ b/admin/mmdvmhost/m17_manager.php @@ -0,0 +1,142 @@ +M17 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (empty($_POST['m17LinkHost'])) { + echo "M17 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (No target specified) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (isset($remoteCommand)) { + echo "M17 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($remoteCommand); + echo "
\n
\n"; + echo ''; + } + } else { + // Output HTML + ?> + M17 Link Manager + + + + + + + + + + + + +
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + + + Link + UnLink + + +
+
+
+ diff --git a/admin/mmdvmhost/nxdn_manager.php b/admin/mmdvmhost/nxdn_manager.php new file mode 100644 index 0000000..efa5747 --- /dev/null +++ b/admin/mmdvmhost/nxdn_manager.php @@ -0,0 +1,114 @@ +NXDN Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (empty($_POST['nxdnLinkHost'])) { + echo "NXDN Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (No target specified) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (isset($remoteCommand)) { + echo "NXDN Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($remoteCommand); + echo "
\n
\n"; + echo ''; + } + } else { + // Output HTML + ?> + NXDN Link Manager +
+ + + + + + + + + + + +
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + + Link + UnLink + + +
+
+
+ diff --git a/admin/mmdvmhost/p25_manager.php b/admin/mmdvmhost/p25_manager.php new file mode 100644 index 0000000..425fdcc --- /dev/null +++ b/admin/mmdvmhost/p25_manager.php @@ -0,0 +1,115 @@ +P25 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (empty($_POST['p25LinkHost'])) { + echo "P25 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (No target specified) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (isset($remoteCommand)) { + echo "P25 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($remoteCommand); + echo "
\n
\n"; + echo ''; + } + } else { + // Output HTML + ?> + P25 Link Manager +
+ + + + + + + + + + + +
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + Link + UnLink + + +
+
+
+ diff --git a/admin/mmdvmhost/pages.php b/admin/mmdvmhost/pages.php new file mode 100644 index 0000000..19c8822 --- /dev/null +++ b/admin/mmdvmhost/pages.php @@ -0,0 +1,137 @@ += 1) { // Check to see if there is a message to decode + $output = "[Skyper Index Rubric:$skyperRubric] ".un_rot(implode($messageTextArray)); + } + else { + $output = "[Skyper Index Rubric:$skyperRubric] No Name"; + } + return $output; + } + + if ($pocsagric == "0004520") { // Skyper Message + if (isset($messageTextArray[0])) { // Rubric Number + $skyperRubric = ord($messageTextArray[0]) - 31; + unset($messageTextArray[0]); + } + if (isset($messageTextArray[1])) { // Message number + $skyperMsgNr = ord($messageTextArray[1]) - 32; + unset($messageTextArray[1]); + } + + if (count($messageTextArray) >= 1) { // Check to see if there is a message to decode + $output = "[Skyper Rubric:$skyperRubric Msg:$skyperMsgNr] ".un_rot(implode($messageTextArray)); + } + else { + $output = "[Skyper Rubric:$skyperRubric] No Message"; + } + return $output; + } +} +?> + + + + + + + + + +setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + $pocsag_timeslot = $dapnetMessageArr["6"]; + $pocsag_ric = str_replace(',', '', $dapnetMessageArr["8"]); + // Fix incorrectly truncated strings containing double quotes + unset($dapnetMessageTxtArr[0]); + if (count($dapnetMessageTxtArr) > 2) { + unset($dapnetMessageTxtArr[count($dapnetMessageTxtArr)]); + $pocsag_msg = implode('"', $dapnetMessageTxtArr); + } else { + $pocsag_msg = $dapnetMessageTxtArr[1]; + } + + // Decode Skyper Messages + if ( ($pocsag_ric == "0004520") || ($pocsag_ric == "0004512") || ($pocsag_ric == "0002504") ) { + $pocsag_msg = skyper($pocsag_msg, $pocsag_ric); + } + + // Formatting long messages without spaces + if (strpos($pocsag_msg, ' ') == 0 && strlen($pocsag_msg) >= 45) { + $pocsag_msg = wordwrap($pocsag_msg, 45, ' ', true); + } + + // Sanitise the data before displaying the HTML + if (isset($local_time)) { $local_time = htmlspecialchars($local_time, ENT_QUOTES, 'UTF-8'); } + if (isset($pocsag_timeslot)) { $pocsag_timeslot = htmlspecialchars($pocsag_timeslot, ENT_QUOTES, 'UTF-8'); } + if (isset($pocsag_ric)) { $pocsag_ric = htmlspecialchars($pocsag_ric, ENT_QUOTES, 'UTF-8'); } + if (isset($pocsag_msg)) { $pocsag_msg = htmlspecialchars($pocsag_msg, ENT_QUOTES, 'UTF-8'); } + +?> + + + + + + + + + + +
()Time in time zoneMessage ModeRIC / CapCode of the receiving PagerMessage contents
diff --git a/admin/mmdvmhost/repeaterinfo.php b/admin/mmdvmhost/repeaterinfo.php new file mode 100644 index 0000000..638e664 --- /dev/null +++ b/admin/mmdvmhost/repeaterinfo.php @@ -0,0 +1,413 @@ + 0) + $configs[$key] = $value; + } + +} + +//Load the DStarRepeater config file +$configdstar = array(); +if ($configdstarfile = fopen('/etc/dstarrepeater','r')) { + while ($line1 = fgets($configdstarfile)) { + if (strpos($line1, '=') !== false) { + list($key1,$value1) = preg_split('/=/',$line1); + $value1 = trim(str_replace('"','',$value1)); + if (strlen($value1) > 0) + $configdstar[$key1] = $value1; + } + } +} + +//Load the dmrgateway config file +$dmrGatewayConfigFile = '/etc/dmrgateway'; +if (fopen($dmrGatewayConfigFile,'r')) { $configdmrgateway = parse_ini_file($dmrGatewayConfigFile, true); } + +//Load the dapnetgateway config file +$dapnetGatewayConfigFile = '/etc/dapnetgateway'; +if (fopen($dapnetGatewayConfigFile,'r')) { $configdapnetgateway = parse_ini_file($dapnetGatewayConfigFile, true); } + +// Load the ysf2dmr config file +if (file_exists('/etc/ysf2dmr')) { + $ysf2dmrConfigFile = '/etc/ysf2dmr'; + if (fopen($ysf2dmrConfigFile,'r')) { $configysf2dmr = parse_ini_file($ysf2dmrConfigFile, true); } +} +// Load the ysf2nxdn config file +if (file_exists('/etc/ysf2nxdn')) { + $ysf2nxdnConfigFile = '/etc/ysf2nxdn'; + if (fopen($ysf2nxdnConfigFile,'r')) { $configysf2nxdn = parse_ini_file($ysf2nxdnConfigFile, true); } +} +// Load the ysf2p25 config file +if (file_exists('/etc/ysf2p25')) { + $ysf2p25ConfigFile = '/etc/ysf2p25'; + if (fopen($ysf2p25ConfigFile,'r')) { $configysf2p25 = parse_ini_file($ysf2p25ConfigFile, true); } +} +// Load the dmr2ysf config file +if (file_exists('/etc/dmr2ysf')) { + $dmr2ysfConfigFile = '/etc/dmr2ysf'; + if (fopen($dmr2ysfConfigFile,'r')) { $configdmr2ysf = parse_ini_file($dmr2ysfConfigFile, true); } +} +// Load the dmr2nxdn config file +if (file_exists('/etc/dmr2nxdn')) { + $dmr2nxdnConfigFile = '/etc/dmr2nxdn'; + if (fopen($dmr2nxdnConfigFile,'r')) { $configdmr2nxdn = parse_ini_file($dmr2nxdnConfigFile, true); } +} +?> + + + + + + + + +
+
+ + + + + + + + + +
+
+ + + +TX $listElem[1]"; + } + else { + if (getActualMode($lastHeard, $mmdvmconfigs) === 'idle') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === NULL) { + if (isProcessRunning("MMDVMHost")) { echo ""; } else { echo ""; } + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'D-Star') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'D-Star') { + echo ""; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'DMR') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'DMR') { + echo ""; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'YSF') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'YSF') { + echo ""; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'P25') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'P25') { + echo ""; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'NXDN') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'NXDN') { + echo ""; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'M17') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'M17') { + echo ""; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'FM') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'FM') { + echo ""; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'POCSAG') { + echo ""; + } + else { + echo ""; + } + } + } +else { + echo ""; +} +?> + + +'."\n"; +} ?> +'."\n"; +} ?> +
TrxListeningListeningOFFLINERX D-StarListening D-StarRX DMRListening DMRRX YSFListening YSFRX P25Listening P25RX NXDNListening NXDNRX M17Listening M17RX FMListening FMPOCSAG".getActualMode($lastHeard, $mmdvmconfigs)."
Tx
Rx
FW'.getDVModemFirmware().'
TCXO'.getDVModemTCXOFreq().'
+ +\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; +if ($configs['aprsEnabled']) { + echo "\n"; +} +if ($configs['ircddbEnabled']) { + echo "\n"; +} +echo "\n"; +echo "
".$lang['dstar_repeater']."
RPT1".str_replace(' ', ' ', $configdstar['callsign'])."
RPT2".str_replace(' ', ' ', $configdstar['gateway'])."
".$lang['dstar_net']."
APRS".substr($configs['aprsHostname'], 0, 16)."
IRC".substr($configs['ircddbHostname'], 0 ,16)."
".getActualLink($reverseLogLinesMMDVM, "D-Star")."
\n"; +} + +$testMMDVModeDMR = getConfigItem("DMR", "Enable", $mmdvmconfigs); +if ( $testMMDVModeDMR == 1 ) { //Hide the DMR information when DMR mode not enabled. +$dmrMasterFile = fopen("/usr/local/etc/DMR_Hosts.txt", "r"); +$dmrMasterHost = getConfigItem("DMR Network", "Address", $mmdvmconfigs); +$dmrMasterPort = getConfigItem("DMR Network", "Port", $mmdvmconfigs); +if ($dmrMasterHost == '127.0.0.1') { + if (isset($configdmrgateway['XLX Network 1']['Address'])) { $xlxMasterHost1 = $configdmrgateway['XLX Network 1']['Address']; } + else { $xlxMasterHost1 = ""; } + $dmrMasterHost1 = $configdmrgateway['DMR Network 1']['Address']; + $dmrMasterHost2 = $configdmrgateway['DMR Network 2']['Address']; + $dmrMasterHost3 = str_replace('_', ' ', $configdmrgateway['DMR Network 3']['Name']); + if (isset($configdmrgateway['DMR Network 4']['Name'])) {$dmrMasterHost4 = str_replace('_', ' ', $configdmrgateway['DMR Network 4']['Name']);} + if (isset($configdmrgateway['DMR Network 5']['Name'])) {$dmrMasterHost5 = str_replace('_', ' ', $configdmrgateway['DMR Network 5']['Name']);} + if (isset($configdmrgateway['DMR Network 6']['Name'])) {$dmrMasterHost6 = str_replace('_', ' ', $configdmrgateway['DMR Network 6']['Name']);} + while (!feof($dmrMasterFile)) { + $dmrMasterLine = fgets($dmrMasterFile); + $dmrMasterHostF = preg_split('/\s+/', $dmrMasterLine); + if ((count($dmrMasterHostF) >= 2) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { + if ((strpos($dmrMasterHostF[0], 'XLX_') === 0) && ($xlxMasterHost1 == $dmrMasterHostF[2])) { $xlxMasterHost1 = str_replace('_', ' ', $dmrMasterHostF[0]); } + if ((strpos($dmrMasterHostF[0], 'CDN_') === 0) && ($dmrMasterHost1 == $dmrMasterHostF[2])) { $dmrMasterHost1 = str_replace('_', ' ', $dmrMasterHostF[0]); } + if ((strpos($dmrMasterHostF[0], 'DMR+_') === 0) && ($dmrMasterHost2 == $dmrMasterHostF[2])) { $dmrMasterHost2 = str_replace('_', ' ', $dmrMasterHostF[0]); } + } + } + if (strlen($xlxMasterHost1) > 19) { $xlxMasterHost1 = substr($xlxMasterHost1, 0, 17) . '..'; } + if (strlen($dmrMasterHost1) > 19) { $dmrMasterHost1 = substr($dmrMasterHost1, 0, 17) . '..'; } + if (strlen($dmrMasterHost2) > 19) { $dmrMasterHost2 = substr($dmrMasterHost2, 0, 17) . '..'; } + if (strlen($dmrMasterHost3) > 19) { $dmrMasterHost3 = substr($dmrMasterHost3, 0, 17) . '..'; } + if (isset($dmrMasterHost4)) { if (strlen($dmrMasterHost4) > 19) { $dmrMasterHost4 = substr($dmrMasterHost4, 0, 17) . '..'; } } + if (isset($dmrMasterHost5)) { if (strlen($dmrMasterHost5) > 19) { $dmrMasterHost5 = substr($dmrMasterHost5, 0, 17) . '..'; } } + if (isset($dmrMasterHost6)) { if (strlen($dmrMasterHost6) > 19) { $dmrMasterHost6 = substr($dmrMasterHost6, 0, 17) . '..'; } } +} +else { + while (!feof($dmrMasterFile)) { + $dmrMasterLine = fgets($dmrMasterFile); + $dmrMasterHostF = preg_split('/\s+/', $dmrMasterLine); + if ((count($dmrMasterHostF) >= 4) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { + if (($dmrMasterHost == $dmrMasterHostF[2]) && ($dmrMasterPort == $dmrMasterHostF[4])) { $dmrMasterHost = str_replace('_', ' ', $dmrMasterHostF[0]); } + } + } + if (strlen($dmrMasterHost) > 19) { $dmrMasterHost = substr($dmrMasterHost, 0, 17) . '..'; } +} +fclose($dmrMasterFile); + +echo "
\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo "\n"; +echo ""; +if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == 1) { echo "\n"; } else { echo "\n"; } +echo ""; +if (getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) == 1) { echo "\n"; } else { echo "\n"; } +echo "\n"; +if (getEnabled("DMR Network", $mmdvmconfigs) == 1) { + if ($dmrMasterHost == '127.0.0.1') { + if ((isset($configdmrgateway['XLX Network 1']['Enabled'])) && ($configdmrgateway['XLX Network 1']['Enabled'] == 1)) { + echo "\n"; + } + if ( !isset($configdmrgateway['XLX Network 1']['Enabled']) && isset($configdmrgateway['XLX Network']['Enabled']) && $configdmrgateway['XLX Network']['Enabled'] == 1) { + if (file_exists("/var/log/pi-star/DMRGateway-".gmdate("Y-m-d").".log")) { $xlxMasterHost1 = exec('grep \'XLX, Linking\|XLX, Unlinking\|XLX, Logged\' /var/log/pi-star/DMRGateway-'.gmdate("Y-m-d").'.log | tail -1 | awk \'{print $5 " " $8 " " $9}\''); } + else { $xlxMasterHost1 = exec('grep \'XLX, Linking\|XLX, Unlinking\|XLX, Logged\' /var/log/pi-star/DMRGateway-'.gmdate("Y-m-d", time() - 86340).'.log | tail -1 | awk \'{print $5 " " $8 " " $9}\''); } + if ( strpos($xlxMasterHost1, 'Linking') !== false ) { $xlxMasterHost1 = str_replace('Linking ', '', $xlxMasterHost1); } + else if ( strpos($xlxMasterHost1, 'Unlinking') !== false ) { $xlxMasterHost1 = "XLX Not Linked"; } + else if ( strpos($xlxMasterHost1, 'Logged') !== false ) { $xlxMasterHost1 = "XLX Not Linked"; } + echo "\n"; + } + if ($configdmrgateway['DMR Network 1']['Enabled'] == 1) { + echo "\n"; + } + if ($configdmrgateway['DMR Network 2']['Enabled'] == 1) { + echo "\n"; + } + if ($configdmrgateway['DMR Network 3']['Enabled'] == 1) { + echo "\n"; + } + if (isset($configdmrgateway['DMR Network 4']['Enabled'])) { + if ($configdmrgateway['DMR Network 4']['Enabled'] == 1) { + echo "\n"; + } + } + if (isset($configdmrgateway['DMR Network 5']['Enabled'])) { + if ($configdmrgateway['DMR Network 5']['Enabled'] == 1) { + echo "\n"; + } + } + if (isset($configdmrgateway['DMR Network 6']['Enabled'])) { + if ($configdmrgateway['DMR Network 6']['Enabled'] == 1) { + echo "\n"; + } + } + } + else { + echo "\n"; + } + } + else { + echo "\n"; + } +echo "
".$lang['dmr_repeater']."
DMR ID".getConfigItem("General", "Id", $mmdvmconfigs)."
DMR CC".getConfigItem("DMR", "ColorCode", $mmdvmconfigs)."
TS1enabled
disabled
TS2enabled
disabled
".$lang['dmr_master']."
".$xlxMasterHost1."
".$xlxMasterHost1."
".$dmrMasterHost1."
".$dmrMasterHost2."
".$dmrMasterHost3."
".$dmrMasterHost4."
".$dmrMasterHost5."
".$dmrMasterHost6."
".$dmrMasterHost."
No DMR Network
\n"; +} + +$testMMDVModeYSF = getConfigItem("System Fusion Network", "Enable", $mmdvmconfigs); +if ( isset($configdmr2ysf['Enabled']['Enabled']) ) { $testDMR2YSF = $configdmr2ysf['Enabled']['Enabled']; } +if ( $testMMDVModeYSF == 1 || $testDMR2YSF ) { //Hide the YSF information when System Fusion Network mode not enabled. + $ysfLinkedTo = getActualLink($reverseLogLinesYSFGateway, "YSF"); + if ($ysfLinkedTo == 'Not Linked' || $ysfLinkedTo == 'Service Not Started') { + $ysfLinkedToTxt = $ysfLinkedTo; + } else { + $ysfHostFile = fopen("/usr/local/etc/YSFHosts.txt", "r"); + $ysfLinkedToTxt = "null"; + while (!feof($ysfHostFile)) { + $ysfHostFileLine = fgets($ysfHostFile); + $ysfRoomTxtLine = preg_split('/;/', $ysfHostFileLine); + if (empty($ysfRoomTxtLine[0]) || empty($ysfRoomTxtLine[1])) continue; + if (($ysfRoomTxtLine[0] == $ysfLinkedTo) || ($ysfRoomTxtLine[1] == $ysfLinkedTo)) { + $ysfLinkedToTxt = $ysfRoomTxtLine[1]; + break; + } + } + if ($ysfLinkedToTxt != "null") { $ysfLinkedToTxt = $ysfLinkedToTxt; } else { $ysfLinkedToTxt = $ysfLinkedTo; } + $ysfLinkedToTxt = str_replace('_', ' ', $ysfLinkedToTxt); + } + if (strlen($ysfLinkedToTxt) > 19) { $ysfLinkedToTxt = substr($ysfLinkedToTxt, 0, 17) . '..'; } + echo "
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "
".$lang['ysf_net']."
".$ysfLinkedToTxt."
\n"; +} + +if ( isset($configysf2dmr['Enabled']['Enabled']) ) { $testYSF2DMR = $configysf2dmr['Enabled']['Enabled']; } +if ( $testYSF2DMR ) { //Hide the YSF2DMR information when YSF2DMR Network mode not enabled. + $dmrMasterFile = fopen("/usr/local/etc/DMR_Hosts.txt", "r"); + $dmrMasterHost = $configysf2dmr['DMR Network']['Address']; + while (!feof($dmrMasterFile)) { + $dmrMasterLine = fgets($dmrMasterFile); + $dmrMasterHostF = preg_split('/\s+/', $dmrMasterLine); + if ((count($dmrMasterHostF) >= 2) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { + if ($dmrMasterHost == $dmrMasterHostF[2]) { $dmrMasterHost = str_replace('_', ' ', $dmrMasterHostF[0]); } + } + } + if (strlen($dmrMasterHost) > 19) { $dmrMasterHost = substr($dmrMasterHost, 0, 17) . '..'; } + fclose($dmrMasterFile); + + echo "
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "
YSF2DMR
DMR ID".$configysf2dmr['DMR Network']['Id']."
YSF2".$lang['dmr_master']."
".$dmrMasterHost."
\n"; +} + +$testMMDVModeP25 = getConfigItem("P25 Network", "Enable", $mmdvmconfigs); +if ( isset($configysf2p25['Enabled']['Enabled']) ) { $testYSF2P25 = $configysf2p25['Enabled']['Enabled']; } +if ( $testMMDVModeP25 == 1 || $testYSF2P25 ) { //Hide the P25 information when P25 Network mode not enabled. + echo "
\n"; + echo "\n"; + if (getConfigItem("P25", "NAC", $mmdvmconfigs)) { + echo "\n"; + echo "\n"; + } else { + echo "\n"; + echo "\n"; + } + echo "\n"; + echo "\n"; + echo "
".$lang['p25_radio']."
NAC".getConfigItem("P25", "NAC", $mmdvmconfigs)."
".$lang['p25_radio']."
NAC0
".$lang['p25_net']."
".getActualLink($logLinesP25Gateway, "P25")."
\n"; +} + +$testMMDVModeNXDN = getConfigItem("NXDN Network", "Enable", $mmdvmconfigs); +if ( isset($configysf2nxdn['Enabled']['Enabled']) ) { if ($configysf2nxdn['Enabled']['Enabled'] == 1) { $testYSF2NXDN = 1; } } +if ( isset($configdmr2nxdn['Enabled']['Enabled']) ) { if ($configdmr2nxdn['Enabled']['Enabled'] == 1) { $testDMR2NXDN = 1; } } +if ( $testMMDVModeNXDN == 1 || isset($testYSF2NXDN) || isset($testDMR2NXDN) ) { //Hide the NXDN information when NXDN Network mode not enabled. + echo "
\n"; + echo "\n"; + if (getConfigItem("NXDN", "RAN", $mmdvmconfigs)) { + echo "\n"; + echo "\n"; + } else { + echo "\n"; + echo "\n"; + } + echo "\n"; + if (file_exists('/etc/nxdngateway')) { + echo "\n"; + } else { + echo "\n"; + } + echo "
".$lang['nxdn_radio']."
RAN".getConfigItem("NXDN", "RAN", $mmdvmconfigs)."
".$lang['nxdn_radio']."
RAN0
".$lang['nxdn_net']."
".getActualLink($logLinesNXDNGateway, "NXDN")."
TG 65000
\n"; +} + +$testMMDVModeM17 = getConfigItem("M17 Network", "Enable", $mmdvmconfigs); +if ( $testMMDVModeM17 == 1 ) { //Hide the M17 information when P25 Network mode not enabled. + echo "
\n"; + echo "\n"; + if (getConfigItem("M17", "CAN", $mmdvmconfigs)) { + echo "\n"; + echo "\n"; + } else { + echo "\n"; + echo "\n"; + } + echo "\n"; + echo "\n"; + echo "
".$lang['m17_radio']."
CAN".getConfigItem("M17", "CAN", $mmdvmconfigs)."
".$lang['m17_radio']."
CAN0
".$lang['m17_net']."
".getActualLink($logLinesM17Gateway, "M17")."
\n"; +} + +$testMMDVModePOCSAG = getConfigItem("POCSAG Network", "Enable", $mmdvmconfigs); +if ( $testMMDVModePOCSAG == 1 ) { //Hide the POCSAG information when POCSAG Network mode not enabled. + echo "
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + if (isset($configdapnetgateway['DAPNET']['Address'])) { + $dapnetGatewayRemoteAddr = $configdapnetgateway['DAPNET']['Address']; + if (strlen($dapnetGatewayRemoteAddr) > 19) { $dapnetGatewayRemoteAddr = substr($dapnetGatewayRemoteAddr, 0, 17) . '..'; } + echo "\n"; + echo "\n"; + } + echo "
POCSAG
Tx".getMHZ(getConfigItem("POCSAG", "Frequency", $mmdvmconfigs))."
POCSAG Master
".$dapnetGatewayRemoteAddr."
\n"; +} +?> diff --git a/admin/mmdvmhost/tgif_links.php b/admin/mmdvmhost/tgif_links.php new file mode 100644 index 0000000..ecf2d26 --- /dev/null +++ b/admin/mmdvmhost/tgif_links.php @@ -0,0 +1,96 @@ +array('timeout' => 2, 'header' => 'User-Agent: Pi-Star Dashboard for '.$dmrID) )); // Add Timout and User Agent to include DMRID + $json_data = file_get_contents("http://tgif.network:5040/api/sessions", false, $jsonContext); + $json = json_decode($json_data, false); + + // Work out what session number we are using + foreach($json as $key => $jsons) { + foreach($jsons as $key => $value) { + if ($json->sessions[$key]->repeater_id == $dmrID) { $session_nr = $key; } + } + } + + // Pull the information from JSON + if (isset($session_nr)) { + $repeaterid = $json->sessions[$session_nr]->repeater_id; + if ($json->sessions[$session_nr]->tg0 == "4000") { $slot1tg = "None"; } else { $slot1tg = "TG".$json->sessions[$session_nr]->tg0; } + if ($json->sessions[$session_nr]->tg == "4000") { $slot2tg = "None"; } else { $slot2tg = "TG".$json->sessions[$session_nr]->tg; } + + echo 'Active TGIF Connections + + + + + + + '."\n"; + + echo ' '."\n"; + echo ' '; + echo ''; + echo ''; + echo ''; + echo ''."\n"; + echo '
DMR MasterConnected MasterRepeater IDThe ID for this Repeater/HotspotSlot1 TGTG linked to Slot 1Slot2 TGTG linked to Slot 2
tgif.network'.$repeaterid.''.$slot1tg.''.$slot2tg.'
'."\n"; + echo '
'."\n"; + } +} +?> diff --git a/admin/mmdvmhost/tgif_manager.php b/admin/mmdvmhost/tgif_manager.php new file mode 100644 index 0000000..70e571b --- /dev/null +++ b/admin/mmdvmhost/tgif_manager.php @@ -0,0 +1,165 @@ + 'Continue', + '101' => 'Switching Protocols', + '200' => 'OK', + '201' => 'Created', + '202' => 'Accepted', + '203' => 'Non-Authoritative Information', + '204' => 'No Content', + '205' => 'Reset Content', + '206' => 'Partial Content', + '300' => 'Multiple Choices', + '302' => 'Found', + '303' => 'See Other', + '304' => 'Not Modified', + '305' => 'Use Proxy', + '400' => 'Bad Request', + '401' => 'Unauthorized', + '402' => 'Payment Required', + '403' => 'Forbidden', + '404' => 'Not Found', + '405' => 'Method Not Allowed', + '406' => 'Not Acceptable', + '407' => 'Proxy Authentication Required', + '408' => 'Request Timeout', + '409' => 'Conflict', + '410' => 'Gone', + '411' => 'Length Required', + '412' => 'Precondition Failed', + '413' => 'Request Entity Too Large', + '414' => 'Request-URI Too Long', + '415' => 'Unsupported Media Type', + '416' => 'Requested Range Not Satisfiable', + '417' => 'Expectation Failed', + '500' => 'Internal Server Error', + '501' => 'Not Implemented', + '502' => 'Bad Gateway', + '503' => 'Service Unavailable', + '504' => 'Gateway Timeout', + '505' => 'HTTP Version Not Supported' + ); + // Caste the status code to a string. + $code = preg_replace("/[^0-9]/", "", $code); + $code = (string)$code; + // Determine if it exists in the array. + if(array_key_exists($code, $statuslist) ) { + // Return the status text + return $statuslist[$code]; + } else { + // If it doesn't exists, degrade by returning the code. + return $code; + } + } + + // Set some Variable + $dmrID = ""; + + // Check if DMR is Enabled + $testMMDVModeDMR = getConfigItem("DMR", "Enable", $mmdvmconfigs); + + if ( $testMMDVModeDMR == 1 ) { + //Load the dmrgateway config file + $dmrGatewayConfigFile = '/etc/dmrgateway'; + if (fopen($dmrGatewayConfigFile,'r')) { $configdmrgateway = parse_ini_file($dmrGatewayConfigFile, true); } + + // Get the current DMR Master from the config + $dmrMasterHost = getConfigItem("DMR Network", "Address", $mmdvmconfigs); + if ( $dmrMasterHost == '127.0.0.1' ) { + // DMRGateway, need to check each config + if (isset($configdmrgateway['DMR Network 1']['Address'])) { + if (($configdmrgateway['DMR Network 1']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 1']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 1']['Id']; + } + } + if (isset($configdmrgateway['DMR Network 2']['Address'])) { + if (($configdmrgateway['DMR Network 2']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 2']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 2']['Id']; + } + } + if (isset($configdmrgateway['DMR Network 3']['Address'])) { + if (($configdmrgateway['DMR Network 3']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 3']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 3']['Id']; + } + } + if (isset($configdmrgateway['DMR Network 4']['Address'])) { + if (($configdmrgateway['DMR Network 4']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 4']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 4']['Id']; + } + } + if (isset($configdmrgateway['DMR Network 5']['Address'])) { + if (($configdmrgateway['DMR Network 5']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 5']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 5']['Id']; + } + } + } else if ( $dmrMasterHost == 'tgif.network' ) { + // MMDVMHost Connected directly to TGIF, get the ID form here + if (getConfigItem("DMR", "Id", $mmdvmconfigs)) { + $dmrID = getConfigItem("DMR", "Id", $mmdvmconfigs); + } else { + $dmrID = getConfigItem("General", "Id", $mmdvmconfigs); + } + } + } + + if ( $dmrID ) { + // Work out if the data has been posted or not + if ( !empty($_POST) && isset($_POST["tgifSubmit"]) ): // Data has been posted for this page + // Are we a repeater + if ( getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" ) { + $targetSlot = "1"; + } else { + $targetSlot = preg_replace("/[^0-9]/", "", $_POST["tgifSlot"]); + $targetSlot--; + } + // Figure out what has been posted + if ( (isset($_POST["tgifNumber"])) && (isset($_POST["tgifSubmit"])) ) { + $targetTG = preg_replace("/[^0-9]/", "", $_POST["tgifNumber"]); + if ($targetTG < 1) { $targetTG = "4000"; } + } else { + $targetTG = "4000"; + } + if ($_POST["tgifAction"] == "UNLINK") { $targetTG = "4000"; } + // Perform the GET request + $tgifApiUrl = "http://tgif.network:5040/api/sessions/update/".$dmrID."/".$targetSlot."/".$targetTG; + $result = file_get_contents($tgifApiUrl); + // Output to the browser + echo 'TGIF Manager'."\n"; + echo "\n\n\n
Command Output
"; + //echo "Sending command to TGIF API"; + echo "TGIF API: "; + echo httpStatusText($result); + echo "
\n"; + echo "
\n"; + // Clean up... + unset($_POST); + echo ''; + else: // Do this when we are not handling post data + echo 'TGIF Manager'."\n"; + echo '
'."\n"; + echo ' + + + + + + + + + + + + +
Talkgroup NumberEnter the Talkgroup numberSlotWhere to link/unlinkLink / UnlinkLink or unlinkActionTake Action
TS1 TS2Link UnLink

'."\n"; + endif; + } +} +?> diff --git a/admin/mmdvmhost/tools.php b/admin/mmdvmhost/tools.php new file mode 100644 index 0000000..20121e6 --- /dev/null +++ b/admin/mmdvmhost/tools.php @@ -0,0 +1,93 @@ + 0) { + $uptimeString .= $days; + $uptimeString .= (($days == 1) ? " day" : " days"); + } + if ($hours > 0) { + $uptimeString .= (($days > 0) ? ", " : "") . $hours; + $uptimeString .= (($hours == 1) ? " hr" : " hrs"); + } + if ($mins > 0) { + $uptimeString .= (($days > 0 || $hours > 0) ? ", " : "") . $mins; + $uptimeString .= (($mins == 1) ? " min" : " mins"); + } + if ($secs > 0) { + $uptimeString .= (($days > 0 || $hours > 0 || $mins > 0) ? ", " : "") . $secs; + $uptimeString .= (($secs == 1) ? " s" : " s"); + } + return $uptimeString; +} + +function startsWith($haystack, $needle) { + return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false; +} + +function getMHZ($freq) { + return substr($freq,0,3) . "." . substr($freq,3,6) . " MHz"; +} + +function isProcessRunning($processName, $full = false, $refresh = false) { + if ($full) { + static $processes_full = array(); + if ($refresh) $processes_full = array(); + if (empty($processes_full)) + exec('ps -eo args', $processes_full); + } else { + static $processes = array(); + if ($refresh) $processes = array(); + if (empty($processes)) + exec('ps -eo comm', $processes); + } + foreach (($full ? $processes_full : $processes) as $processString) { + if (strpos($processString, $processName) !== false) + return true; + } + return false; +} + +function createConfigLines() { + $out =""; + foreach($_GET as $key=>$val) { + if($key != "cmd") { + $out .= "define(\"$key\", \"$val\");"."\n"; + } + } + return $out; +} + +function getSize($filesize, $precision = 2) { + $units = array('', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'); + foreach ($units as $idUnit => $unit) { + if ($filesize > 1024) + $filesize /= 1024; + else + break; + } + return round($filesize, $precision).' '.$units[$idUnit].'B'; +} + +function checkSetup() { + $el = error_reporting(); + error_reporting(E_ERROR | E_WARNING | E_PARSE); + if (defined(DISTRIBUTION)) { +?> + + + + diff --git a/admin/mmdvmhost/ysf_manager.php b/admin/mmdvmhost/ysf_manager.php new file mode 100644 index 0000000..96af8ce --- /dev/null +++ b/admin/mmdvmhost/ysf_manager.php @@ -0,0 +1,139 @@ +YSF Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (empty($_POST['ysfLinkHost'])) { + echo "YSF Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (No target specified) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (isset($remoteCommand)) { + echo "YSF Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($remoteCommand); + echo "
\n
\n"; + echo ''; + } + } else { + // Output HTML + ?> + YSF Link Manager + + + + + + + + + + + + +
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + Link + UnLink + + +
+
+
+ diff --git a/admin/pistar-keeper-download.php b/admin/pistar-keeper-download.php index 2bd7d3d..0b2352e 100644 --- a/admin/pistar-keeper-download.php +++ b/admin/pistar-keeper-download.php @@ -1,18 +1,4 @@ diff --git a/admin/power.php b/admin/power.php index 4d1d670..121504d 100644 --- a/admin/power.php +++ b/admin/power.php @@ -1,32 +1,4 @@ @@ -54,96 +23,70 @@ if ($_SERVER["PHP_SELF"] == "/admin/power.php") { - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['power'];?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['power'];?> -
-
Pi-Star: /
-

Pi-Star

+
CDN: /
+

CDN

| | - | |

- - - +

+ +
'; + '; system('sudo sync && sudo sync && sudo sync && sudo mount -o remount,ro / > /dev/null &'); exec('sudo reboot > /dev/null &'); }; - if ( $_POST["action"] === "shutdown" ) { - echo ''; + if ( escapeshellcmd($_POST["action"]) == "shutdown" ) { + echo '
Shutdown command has been sent to your Pi, +
please wait 30 secs for it to fully shutdown
before removing the power.
'; system('sudo sync && sudo sync && sudo sync && sudo mount -o remount,ro / > /dev/null &'); exec('sudo shutdown -h now > /dev/null &'); }; ?> -


Reboot command has been sent to your Pi, + if ( escapeshellcmd($_POST["action"]) == "reboot" ) { + echo '
Reboot command has been sent to your Pi,
please wait up to 90 secs for it to reboot.

You will be re-directed back to the -
dashboard automatically in 90 seconds.


+
dashboard automatically in 90 seconds. -


Shutdown command has been sent to your Pi, -
please wait 30 secs for it to fully shutdown
before removing the power.


+
" method="post" onsubmit="return confirm('Are you sure?');"> - - - - - - - - - -
- Reboot
- -
- Shutdown
- -
+
+ + +
-
-
diff --git a/admin/sysinfo.php b/admin/sysinfo.php index 33ba415..c99ef20 100644 --- a/admin/sysinfo.php +++ b/admin/sysinfo.php @@ -1,23 +1,4 @@ with `-v` to print version - * banners (MMDVMHost, DMRGateway, DMR2YSF/NXDN, YSFGateway, - * DGIdGateway, YSF2DMR/P25/NXDN, P25Gateway, NXDNGateway, - * M17Gateway, DAPNETGateway). - */ -require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php'); -require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc'); -setSecurityHeaders(); - -// Layer 2 of the default-password protection — see config/banner_warnings.inc. -// MUST run BEFORE any output so header('Location: ...') works. -pistar_warnings_enforce_redirect(); - // Load the language support require_once('config/language.php'); // Load the Pi-Star Release file @@ -30,8 +11,7 @@ require_once('config/version.php'); // Retrieve server information $system = system_information(); -function system_information() -{ +function system_information() { @list($system, $host, $kernel) = preg_split('/[\s,]+/', php_uname('a'), 5); $meminfo = false; if (@is_readable('/proc/meminfo')) { @@ -49,9 +29,8 @@ function system_information() 'partitions' => disk_list() ); } - -function disk_list() -{ + +function disk_list() { $partitions = array(); // Fetch partition information from df command // I would have used disk_free_space() and disk_total_space() here but @@ -64,7 +43,7 @@ function disk_list() $column = trim($column); if($column != '') $columns[] = $column; } - + // Only process 6 column rows // (This has the bonus of ignoring the first row which is 7) if(count($columns) == 6) { @@ -88,8 +67,7 @@ function disk_list() return $partitions; } -function formatSize( $bytes ) -{ +function formatSize( $bytes ) { $types = array( 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ); for( $i = 0; $bytes >= 1024 && $i < ( count( $types ) -1 ); $bytes /= 1024, $i++ ); return( round( $bytes, 2 ) . " " . $types[$i] ); @@ -105,40 +83,22 @@ function formatSize( $bytes ) - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?> - -
-
Pi-Star: / Dashboard:
-

Pi-Star -

+
CDN: / Dashboard:
+

CDN -

| | @@ -148,20 +108,21 @@ function formatSize( $bytes )

- - +

CDN System Information

\n"; + echo "

Memory

\n
\n"; $sysRamUsed = $system['mem_info']['MemTotal'] - $system['mem_info']['MemFree'] - $system['mem_info']['Buffers'] - $system['mem_info']['Cached']; $sysRamPercent = sprintf('%.2f',($sysRamUsed / $system['mem_info']['MemTotal']) * 100); - echo "
\n"; + echo "
RAM
\n"; + echo "
".$sysRamPercent."% used
\n"; + echo "
Total: ".formatSize($system['mem_info']['MemTotal'])."   Used: ".formatSize($sysRamUsed)."   Free: ".formatSize($system['mem_info']['MemTotal'] - $sysRamUsed)."
\n"; + echo "
\n \n"; } // Filesystem Information if (count($system['partitions']) > 0) { - echo " \n"; + echo "

Mounted Filesystems

\n
\n"; foreach($system['partitions'] as $fs) { if ($fs['Used']['value'] > 0 && $fs['FileSystem']['text']!= "none" && $fs['FileSystem']['text']!= "udev") { $diskFree = $fs['Free']['value']; @@ -169,75 +130,71 @@ if (count($system['partitions']) > 0) { $diskUsed = $fs['Used']['value']; $diskPercent = sprintf('%.2f',($diskUsed / $diskTotal) * 100); - echo "
\n"; + echo "
".$fs['Partition']['text']."
\n"; + echo "
".$diskPercent."% used
\n"; + echo "
Total: ".formatSize($diskTotal)."   Used: ".formatSize($diskUsed)."   Free: ".formatSize($diskFree)."
\n"; + echo "
\n"; } } + echo " \n"; } // Binary Information -echo " \n"; +echo "

Installed Binaries

\n
\n"; if (is_executable('/usr/local/bin/MMDVMHost')) { $MMDVMHost_Ver = exec('/usr/local/bin/MMDVMHost -v | cut -d\' \' -f 3-'); - echo "
\n"; + echo "
MMDVMHost
".$MMDVMHost_Ver."
\n"; } if (is_executable('/usr/local/bin/DMRGateway')) { $DMRGateway_Ver = exec('/usr/local/bin/DMRGateway -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
DMRGateway
".$DMRGateway_Ver."
\n"; } if (is_executable('/usr/local/bin/DMR2YSF')) { $DMR2YSF_Ver = exec('/usr/local/bin/DMR2YSF -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
DMR2YSF
".$DMR2YSF_Ver."
\n"; } if (is_executable('/usr/local/bin/DMR2NXDN')) { $DMR2NXDN_Ver = exec('/usr/local/bin/DMR2NXDN -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
DMR2NXDN
".$DMR2NXDN_Ver."
\n"; } if (is_executable('/usr/local/bin/YSFGateway')) { $YSFGateway_Ver = exec('/usr/local/bin/YSFGateway -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
YSFGateway
".$YSFGateway_Ver."
\n"; } if (is_executable('/usr/local/bin/DGIdGateway')) { $DGIdGateway_Ver = exec('/usr/local/bin/DGIdGateway -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
DGIdGateway
".$DGIdGateway_Ver."
\n"; } if (is_executable('/usr/local/bin/YSF2DMR')) { $YSF2DMR_Ver = exec('/usr/local/bin/YSF2DMR -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
YSF2DMR
".$YSF2DMR_Ver."
\n"; } if (is_executable('/usr/local/bin/YSF2P25')) { $YSF2P25_Ver = exec('/usr/local/bin/YSF2P25 -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
YSF2P25
".$YSF2P25_Ver."
\n"; } if (is_executable('/usr/local/bin/YSF2NXDN')) { $YSF2NXDN_Ver = exec('/usr/local/bin/YSF2NXDN -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
YSF2NXDN
".$YSF2NXDN_Ver."
\n"; } if (is_executable('/usr/local/bin/P25Gateway')) { $P25Gateway_Ver = exec('/usr/local/bin/P25Gateway -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
P25Gateway
".$P25Gateway_Ver."
\n"; } if (is_executable('/usr/local/bin/NXDNGateway')) { $NXDNGateway_Ver = exec('/usr/local/bin/NXDNGateway -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
NXDNGateway
".$NXDNGateway_Ver."
\n"; } if (is_executable('/usr/local/bin/M17Gateway')) { $M17Gateway_Ver = exec('/usr/local/bin/M17Gateway -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
M17Gateway
".$M17Gateway_Ver."
\n"; } if (is_executable('/usr/local/bin/DAPNETGateway')) { $DAPNETGateway_Ver = exec('/usr/local/bin/DAPNETGateway -v | cut -d\' \' -f 3-'); - echo " \n"; + echo "
DAPNETGateway
".$DAPNETGateway_Ver."
\n"; } +echo " \n"; ?> -
Pi-Star System Information
MemoryStats
RAM
Used ".$sysRamPercent."%
"; - echo " Total: ".formatSize($system['mem_info']['MemTotal'])." Used: ".formatSize($sysRamUsed)." Free: ".formatSize($system['mem_info']['MemTotal'] - $sysRamUsed)."
MountStats
".$fs['Partition']['text']."
Used ".$diskPercent."%
"; - echo " Total: ".formatSize($diskTotal)." Used: ".formatSize($diskUsed)." Free: ".formatSize($diskFree)."
BinaryVersion
MMDVMHost".$MMDVMHost_Ver."
DMRGateway".$DMRGateway_Ver."
DMR2YSF".$DMR2YSF_Ver."
DMR2NXDN".$DMR2NXDN_Ver."
YSFGateway".$YSFGateway_Ver."
DGIdGateway".$DGIdGateway_Ver."
YSF2DMR".$YSF2DMR_Ver."
YSF2P25".$YSF2P25_Ver."
YSF2NXDN".$YSF2NXDN_Ver."
P25Gateway".$P25Gateway_Ver."
NXDNGateway".$NXDNGateway_Ver."
M17Gateway".$M17Gateway_Ver."
DAPNETGateway".$DAPNETGateway_Ver."
-
-
- diff --git a/admin/update.php b/admin/update.php index 4638207..c143dec 100644 --- a/admin/update.php +++ b/admin/update.php @@ -1,34 +1,4 @@ log` pair - // tried to do. The earlier echo was buggy (the `>` redirect was - // run as www-data, not under sudo, so it could only ever truncate - // a www-data-writable file — a silent no-op when the log was last - // touched as root). Run synchronously, BEFORE the backgrounded - // pistar-update spawn, so the script's first writes always land - // in a freshly cleared file regardless of `&` scheduling. - system('sudo truncate -s 0 /var/log/pi-star/pi-star_update.log'); - system('sudo /usr/local/sbin/pistar-update > /dev/null 2>&1 &'); - } - - // Sanity Check Passed. - header('Cache-Control: no-cache'); - // session_start() is no longer called here — csrf_verify() at - // the top of the file already started the session via - // csrf_session_start(). A second session_start() would emit a - // "session is already active" NOTICE on PHP 8.x. The existing - // $_SESSION['update_offset'] log-tail logic below works - // unchanged against the already-active session. - - // Initialize session offset only if update has been confirmed - if (!isset($_GET['ajax']) && !empty($_POST) && isset($_POST['confirm_update'])) { - //unset($_SESSION['update_offset']); - if (file_exists('/var/log/pi-star/pi-star_update.log')) { - $_SESSION['update_offset'] = filesize('/var/log/pi-star/pi-star_update.log'); - } else { - $_SESSION['update_offset'] = 0; - } - } - - if (isset($_GET['ajax'])) { - //session_start(); - if (!file_exists('/var/log/pi-star/pi-star_update.log')) { - exit(); - } - - $handle = fopen('/var/log/pi-star/pi-star_update.log', 'rb'); - if (isset($_SESSION['update_offset'])) { - fseek($handle, 0, SEEK_END); - if ($_SESSION['update_offset'] > ftell($handle)) //log rotated/truncated - $_SESSION['update_offset'] = 0; //continue at beginning of the new log - $data = stream_get_contents($handle, -1, $_SESSION['update_offset']); - $_SESSION['update_offset'] += strlen($data); - echo nl2br($data); - } - else { - fseek($handle, 0, SEEK_END); - $_SESSION['update_offset'] = ftell($handle); - } +// Web-based update has been disabled. +if (isset($_GET['ajax'])) { exit(); - } +} +header('Cache-Control: no-cache'); ?> @@ -114,97 +24,34 @@ if ($_SERVER["PHP_SELF"] == "/admin/update.php") { - - + + - Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?> + CDN - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?> - - - - - -
-
-
-
- Pi-Star: / Dashboard: -
-

Pi-Star -

- -
-
-
-
- - - - -
Update Running
Starting update, please wait...
- -
" method="post"> - - - - - - - - -
-

- This will update your Pi-Star installation to the latest version.
-
- The update process may take several minutes to complete.
- Please do not interrupt the process or power off your system during the update. -

- -
-
- -
-
- +
+
CDN: / Dashboard:
+

CDN -

+

+ | + | + | + | + +

+
+
+

Update Disabled

+
+
Web-based updates have been disabled on this system.
+
+
- - $arrConfig One line per element. - * @return array Keyed by the LHS of the first `=` per line. - */ -function ParseConfig($arrConfig) -{ - $config = array(); - foreach ($arrConfig as $line) { - if ($line[0] != "#") { - $arrLine = explode("=", $line); - $config[$arrLine[0]] = $arrLine[1]; - } - } - return $config; +function ParseConfig($arrConfig) { + $config = array(); + foreach($arrConfig as $line) { + if($line[0] != "#") { + $arrLine = explode("=",$line); + $config[$arrLine[0]] = $arrLine[1]; + } + } + return $config; } -/** - * Map a wireless centre frequency to a friendly channel label. - * - * Accepts either MHz integers (e.g. "2412" → "2.4GHz Ch1", "5180" → - * "5.0GHz Ch36") or some legacy short forms emitted by older `iw` - * builds (e.g. "504" / "508" for 5GHz channels in the 5MHz grid). - * - * @param string $freq Centre frequency as reported by iwconfig/iw. - * @return string Friendly channel label, or "Invalid Channel" if unmapped. - */ -function ConvertToChannel($freq) -{ - $wifiFreqToChan = array ( - "2412" => "2.4GHz Ch1", - "2417" => "2.4GHz Ch2", - "2422" => "2.4GHz Ch3", - "2427" => "2.4GHz Ch4", - "2432" => "2.4GHz Ch5", - "2437" => "2.4GHz Ch6", - "2442" => "2.4GHz Ch7", - "2447" => "2.4GHz Ch8", - "2452" => "2.4GHz Ch9", - "2457" => "2.4GHz Ch10", - "2462" => "2.4GHz Ch11", - "2467" => "2.4GHz Ch12", - "2472" => "2.4GHz Ch13", - "2484" => "2.4GHz Ch14", - "504" => "5.0GHz Ch8", - "506" => "5.0GHz Ch12", - "508" => "5.0GHz Ch16", - "517" => "5.0GHz Ch34", - "518" => "5.0GHz Ch36", - "519" => "5.0GHz Ch38", - "520" => "5.0GHz Ch40", - "521" => "5.0GHz Ch42", - "522" => "5.0GHz Ch44", - "523" => "5.0GHz Ch46", - "524" => "5.0GHz Ch48", - "526" => "5.0GHz Ch52", - "528" => "5.0GHz Ch56", - "530" => "5.0GHz Ch60", - "532" => "5.0GHz Ch64", - "550" => "5.0GHz Ch100", - "552" => "5.0GHz Ch104", - "554" => "5.0GHz Ch108", - "556" => "5.0GHz Ch112", - "558" => "5.0GHz Ch116", - "560" => "5.0GHz Ch120", - "562" => "5.0GHz Ch124", - "564" => "5.0GHz Ch128", - "566" => "5.0GHz Ch132", - "568" => "5.0GHz Ch136", - "570" => "5.0GHz Ch140", - "492" => "5.0GHz Ch184", - "494" => "5.0GHz Ch188", - "496" => "5.0GHz Ch192", - "498" => "5.0GHz Ch196", - "5035" => "5.0GHz Ch7", - "5040" => "5.0GHz Ch8", - "5045" => "5.0GHz Ch9", - "5055" => "5.0GHz Ch11", - "5060" => "5.0GHz Ch12", - "5080" => "5.0GHz Ch16", - "5170" => "5.0GHz Ch34", - "5180" => "5.0GHz Ch36", - "5190" => "5.0GHz Ch38", - "5200" => "5.0GHz Ch40", - "5210" => "5.0GHz Ch42", - "5220" => "5.0GHz Ch44", - "5230" => "5.0GHz Ch46", - "5240" => "5.0GHz Ch48", - "5260" => "5.0GHz Ch52", - "5280" => "5.0GHz Ch56", - "5300" => "5.0GHz Ch60", - "5320" => "5.0GHz Ch64", - "5500" => "5.0GHz Ch100", - "5520" => "5.0GHz Ch104", - "5540" => "5.0GHz Ch108", - "5560" => "5.0GHz Ch112", - "5580" => "5.0GHz Ch116", - "5600" => "5.0GHz Ch120", - "5620" => "5.0GHz Ch124", - "5640" => "5.0GHz Ch128", - "5660" => "5.0GHz Ch132", - "5680" => "5.0GHz Ch136", - "5700" => "5.0GHz Ch140", - "5745" => "5.0GHz Ch149", - "5765" => "5.0GHz Ch153", - "5785" => "5.0GHz Ch157", - "5805" => "5.0GHz Ch161", - "5825" => "5.0GHz Ch165", - "4915" => "5.0GHz Ch183", - "4920" => "5.0GHz Ch184", - "4925" => "5.0GHz Ch185", - "4935" => "5.0GHz Ch187", - "4940" => "5.0GHz Ch188", - "4945" => "5.0GHz Ch189", - "4960" => "5.0GHz Ch192", - "4980" => "5.0GHz Ch196" - ); - if (array_key_exists($freq, $wifiFreqToChan)) { return $wifiFreqToChan[$freq]; } - else { return "Invalid Channel"; } +function ConvertToChannel($freq) { + $wifiFreqToChan = array ( + "2412" => "2.4GHz Ch1", + "2417" => "2.4GHz Ch2", + "2422" => "2.4GHz Ch3", + "2427" => "2.4GHz Ch4", + "2432" => "2.4GHz Ch5", + "2437" => "2.4GHz Ch6", + "2442" => "2.4GHz Ch7", + "2447" => "2.4GHz Ch8", + "2452" => "2.4GHz Ch9", + "2457" => "2.4GHz Ch10", + "2462" => "2.4GHz Ch11", + "2467" => "2.4GHz Ch12", + "2472" => "2.4GHz Ch13", + "2484" => "2.4GHz Ch14", + "504" => "5.0GHz Ch8", + "506" => "5.0GHz Ch12", + "508" => "5.0GHz Ch16", + "517" => "5.0GHz Ch34", + "518" => "5.0GHz Ch36", + "519" => "5.0GHz Ch38", + "520" => "5.0GHz Ch40", + "521" => "5.0GHz Ch42", + "522" => "5.0GHz Ch44", + "523" => "5.0GHz Ch46", + "524" => "5.0GHz Ch48", + "526" => "5.0GHz Ch52", + "528" => "5.0GHz Ch56", + "530" => "5.0GHz Ch60", + "532" => "5.0GHz Ch64", + "550" => "5.0GHz Ch100", + "552" => "5.0GHz Ch104", + "554" => "5.0GHz Ch108", + "556" => "5.0GHz Ch112", + "558" => "5.0GHz Ch116", + "560" => "5.0GHz Ch120", + "562" => "5.0GHz Ch124", + "564" => "5.0GHz Ch128", + "566" => "5.0GHz Ch132", + "568" => "5.0GHz Ch136", + "570" => "5.0GHz Ch140", + "492" => "5.0GHz Ch184", + "494" => "5.0GHz Ch188", + "496" => "5.0GHz Ch192", + "498" => "5.0GHz Ch196", + "5035" => "5.0GHz Ch7", + "5040" => "5.0GHz Ch8", + "5045" => "5.0GHz Ch9", + "5055" => "5.0GHz Ch11", + "5060" => "5.0GHz Ch12", + "5080" => "5.0GHz Ch16", + "5170" => "5.0GHz Ch34", + "5180" => "5.0GHz Ch36", + "5190" => "5.0GHz Ch38", + "5200" => "5.0GHz Ch40", + "5210" => "5.0GHz Ch42", + "5220" => "5.0GHz Ch44", + "5230" => "5.0GHz Ch46", + "5240" => "5.0GHz Ch48", + "5260" => "5.0GHz Ch52", + "5280" => "5.0GHz Ch56", + "5300" => "5.0GHz Ch60", + "5320" => "5.0GHz Ch64", + "5500" => "5.0GHz Ch100", + "5520" => "5.0GHz Ch104", + "5540" => "5.0GHz Ch108", + "5560" => "5.0GHz Ch112", + "5580" => "5.0GHz Ch116", + "5600" => "5.0GHz Ch120", + "5620" => "5.0GHz Ch124", + "5640" => "5.0GHz Ch128", + "5660" => "5.0GHz Ch132", + "5680" => "5.0GHz Ch136", + "5700" => "5.0GHz Ch140", + "5745" => "5.0GHz Ch149", + "5765" => "5.0GHz Ch153", + "5785" => "5.0GHz Ch157", + "5805" => "5.0GHz Ch161", + "5825" => "5.0GHz Ch165", + "4915" => "5.0GHz Ch183", + "4920" => "5.0GHz Ch184", + "4925" => "5.0GHz Ch185", + "4935" => "5.0GHz Ch187", + "4940" => "5.0GHz Ch188", + "4945" => "5.0GHz Ch189", + "4960" => "5.0GHz Ch192", + "4980" => "5.0GHz Ch196" + ); + if (array_key_exists($freq, $wifiFreqToChan)) { return $wifiFreqToChan[$freq]; } + else { return "Invalid Channel"; } } -/** - * Map a wpa_supplicant security flag string to a human-friendly label. - * - * Input is the bracketed token list reported by `wpa_cli scan_results` - * (e.g. "[WPA2-PSK-CCMP][ESS]" → "WPA2-PSK (AES)"). Unknown flag strings - * fall through to the default branch and are returned verbatim so the - * UI never silently swallows a network it doesn't recognise. - * - * @param string $security Bracketed flag list from wpa_cli output. - * @return string Friendly security descriptor, or the raw flag string. - */ -function ConvertToSecurity($security) -{ - switch ($security) { - case "[WPA2-PSK-CCMP][ESS]": - return "WPA2-PSK (AES)"; - break; - case "[WPA2-PSK-CCMP-preauth][ESS]": - return "WPA2-PSK (AES) with Preauth"; - break; - case "[WPA2-PSK-TKIP][ESS]": - return "WPA2-PSK (TKIP)"; - break; - case "[WPA2-PSK-CCMP][WPS][ESS]": - return "WPA2-PSK (TKIP) with WPS"; - break; - case "[WPA-PSK-TKIP+CCMP][WPS][ESS]": - return "WPA-PSK (TKIP/AES) with WPS"; - break; - case "[WPA-PSK-TKIP][WPA2-PSK-CCMP][WPS][ESS]": - return "WPA/WPA2-PSK (TKIP)"; - break; - case "[WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][ESS]": - return "WPA/WPA2-PSK (TKIP/AES)"; - break; - case "[WPA-EAP-CCMP+TKIP][WPA2-EAP-CCMP+TKIP-preauth][ESS]": - return "WPA/WPA2-PSK (TKIP/AES) with Preauth"; - break; - case "[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]": - return "WPA/WPA2-PSK (TKIP/AES) with WPS"; - break; - case "[WPA-PSK-CCMP][WPA2-PSK-CCMP][WPS][ESS]": - return "WPA/WPA2-PSK (AES) with WPS"; - break; - case "[WPA-PSK-TKIP][ESS]": - return "WPA-PSK (TKIP)"; - break; - case "[WEP][ESS]": - return "WEP"; - break; - case "[ESS]": - return "None"; - break; - default: - return $security; - break; - } +function ConvertToSecurity($security) { + switch($security) { + case "[WPA2-PSK-CCMP][ESS]": + return "WPA2-PSK (AES)"; + break; + case "[WPA2-PSK-CCMP-preauth][ESS]": + return "WPA2-PSK (AES) with Preauth"; + break; + case "[WPA2-PSK-TKIP][ESS]": + return "WPA2-PSK (TKIP)"; + break; + case "[WPA2-PSK-CCMP][WPS][ESS]": + return "WPA2-PSK (TKIP) with WPS"; + break; + case "[WPA-PSK-TKIP+CCMP][WPS][ESS]": + return "WPA-PSK (TKIP/AES) with WPS"; + break; + case "[WPA-PSK-TKIP][WPA2-PSK-CCMP][WPS][ESS]": + return "WPA/WPA2-PSK (TKIP)"; + break; + case "[WPA-PSK-TKIP+CCMP][WPA2-PSK-TKIP+CCMP][ESS]": + return "WPA/WPA2-PSK (TKIP/AES)"; + break; + case "[WPA-EAP-CCMP+TKIP][WPA2-EAP-CCMP+TKIP-preauth][ESS]": + return "WPA/WPA2-PSK (TKIP/AES) with Preauth"; + break; + case "[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][WPS][ESS]": + return "WPA/WPA2-PSK (TKIP/AES) with WPS"; + break; + case "[WPA-PSK-CCMP][WPA2-PSK-CCMP][WPS][ESS]": + return "WPA/WPA2-PSK (AES) with WPS"; + break; + case "[WPA-PSK-TKIP][ESS]": + return "WPA-PSK (TKIP)"; + break; + case "[WEP][ESS]": + return "WEP"; + break; + case "[ESS]": + return "None"; + break; + default: + return $security; + break; + } } + +?> + diff --git a/admin/wifi/styles.php b/admin/wifi/styles.php index f67f74e..39952ed 100644 --- a/admin/wifi/styles.php +++ b/admin/wifi/styles.php @@ -1,75 +1,77 @@ body { - background-color: #; + background-color: #; + color: #; + font: 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + margin: 0; + padding: 20px; + box-sizing: border-box; } .red { - color:red; + color:#c0392b; + font-weight:bold; } .green { - color:green; + color:#1e8f4e; + font-weight:bold; } .network { - border:1px solid; + border:1px solid rgba(0,0,0,0.1); + border-radius:10px; text-align:left; - padding-top:5px; - padding-left:5px; - background-color: #; + padding:12px 14px; + margin-bottom: 12px; + background-color: #; + box-shadow: 0 1px 3px rgba(0,0,0,0.04); +} + +/* Per-network entry box - the JS-generated markup spells this class two + different ways ("NetworkBoxes" from PHP, "Networkboxes" from functions.js), + so both are styled here to look right regardless of which path renders it. */ +.NetworkBoxes, .Networkboxes { + border:1px solid rgba(0,0,0,0.08); + border-radius:8px; + background-color: #; + padding: 10px 12px 12px 12px; + margin-bottom: 10px; + font-weight: 700; } .tableft { @@ -81,76 +83,122 @@ body { textarea { width:699px; height:499px; + border-radius:8px; + border:1px solid rgba(0,0,0,0.18); } input.button { width:80%; - border:1px solid; + border:1px solid rgba(0,0,0,0.2); + border-radius:8px; } input[type=text],input[type=password] { - border:1px solid; + border:1px solid rgba(0,0,0,0.2); + border-radius:6px; + padding: 5px 8px; } input[type=button],input[type=submit] { - border:1px solid; - border-radius:5px; + background: #; + color: #; + border:none; + border-radius:999px; + padding: 9px 20px; + font-weight: 600; + cursor:pointer; + box-shadow: 0 2px 6px rgba(15,23,42,0.16); + transition: filter 0.15s ease, box-shadow 0.15s ease; +} + +input[type=button]:hover,input[type=submit]:hover { + filter: brightness(1.08); + box-shadow: 0 4px 10px rgba(15,23,42,0.22); } .infoheader { width:100%; text-align:center; - margin-top:10px; - border-bottom: 1px solid; + font-weight: 700; + font-size: 15px; + margin-top:14px; + margin-bottom: 12px; + padding-bottom: 10px; + border-bottom: 1px solid rgba(0,0,0,0.08); } .infobox { - background-color: #; - font-weight: bold; + background-color: #; width:100%; + border-radius:12px; + border: 1px solid rgba(0,0,0,0.08); + box-shadow: 0 1px 3px rgba(0,0,0,0.04); + padding: 16px 18px; + margin-bottom: 16px; + box-sizing: border-box; +} + +.infobox form { + display: flex; + flex-wrap: wrap; + gap: 10px; } .intinfo { - background-color: #; + background-color: #; color: #; width: 398px; text-align: left; - border-right: 1px solid; - border-left: 1px solid; + border: 1px solid rgba(0,0,0,0.08); + border-radius: 12px 0 0 12px; + border-right: none; float: left; - border-bottom:1px solid; - font-family: "Courier New", Courier, monospace; + box-sizing: border-box; + padding: 0 14px 10px 14px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; } .wifiinfo { - background-color: #; + background-color: #; color: #; margin: 0 0 0 400px; - border-right: 1px solid; + border: 1px solid rgba(0,0,0,0.08); + border-radius: 0 12px 12px 0; text-align: left; - border-bottom:1px solid; - font-family: "Courier New", Courier, monospace; + box-sizing: border-box; + padding: 0 14px 10px 14px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; } .intheader { - background-color: #; - color: #; - text-align:center; + background: transparent; + color: #; + text-align:left; width:100%; - font-weight: bold; + box-sizing: border-box; + padding: 12px 0 10px 0; + font-weight: 700; + font-size: 11px; + text-transform: uppercase; + letter-spacing: 0.04em; + border-bottom: 2px solid #; } .intfooter { - background-color: #; - color: #; + background: transparent; + color: #6b7280; width:100%; - border-top:1px solid; + box-sizing: border-box; + padding: 10px 4px 0 4px; + border-top:1px solid rgba(0,0,0,0.08); float:left; text-align:center; + font-size: 11px; } .tail { - background-color: #; - color: #; + background-color: transparent; + color: transparent; width:100%; + height: 1px; } diff --git a/api/last_heard.php b/api/last_heard.php index be72695..f8e49bf 100644 --- a/api/last_heard.php +++ b/api/last_heard.php @@ -1,65 +1,31 @@ diff --git a/config/banner_warnings.inc b/config/banner_warnings.inc deleted file mode 100644 index 524994a..0000000 --- a/config/banner_warnings.inc +++ /dev/null @@ -1,427 +0,0 @@ - shape used throughout the - * dashboard (no CSS class — same convention as the existing banners - * in index.php / configure.php this file replaces). - * - * @param string $html Banner body. INTERPOLATED RAW — callers must - * ensure any dynamic content is already escaped - * (none of the current banners include dynamic - * content, so this is a non-issue today; flagged - * for any future caller). - * @param string $level 'warn' (yellow) or 'danger' (red). - * - * @return void - */ -function _pistar_banner_emit($html, $level = 'warn') -{ - $style = ($level === 'danger') - ? 'background-color: #ff9090; color: #f01010;' - : 'background-color: #ffff90; color: #906000;'; - echo '
' . "\n"; - echo '
' . "\n"; - echo ' ' . "\n"; - echo ' ' . "\n"; - echo ' ' . "\n"; - echo '
' . $html . '
' . "\n"; - echo '
' . "\n"; -} - -/** - * Extract the HTTP Basic auth user + password from the current request. - * - * On Pi-Star's stock nginx + PHP-FPM config, $_SERVER['PHP_AUTH_PW'] - * is populated automatically (PHP synthesises it from the forwarded - * Authorization header). The HTTP_AUTHORIZATION fallback handles - * unusual setups where only the raw header survives. - * - * Note: the REMOTE_USER fallback only sets $user — that var contains - * the authenticated username but never the password. Callers that need - * the password (default-password check, etc.) treat empty $pw as - * "unable to verify" and fail closed. - * - * @return array{0: string, 1: string} [$user, $password]; either or - * both may be '' when basic auth - * hasn't happened (e.g. on the - * unauthenticated public root). - */ -function _pistar_get_basic_auth() -{ - $user = isset($_SERVER['PHP_AUTH_USER']) ? (string)$_SERVER['PHP_AUTH_USER'] : ''; - $pw = isset($_SERVER['PHP_AUTH_PW']) ? (string)$_SERVER['PHP_AUTH_PW'] : ''; - if ($user !== '' && $pw !== '') { - return array($user, $pw); - } - if (!empty($_SERVER['HTTP_AUTHORIZATION']) - && stripos($_SERVER['HTTP_AUTHORIZATION'], 'Basic ') === 0) { - $decoded = base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6), true); - if ($decoded !== false && strpos($decoded, ':') !== false) { - list($user, $pw) = explode(':', $decoded, 2); - return array($user, $pw); - } - } - if ($user === '' && !empty($_SERVER['REMOTE_USER'])) { - $user = (string)$_SERVER['REMOTE_USER']; - } - return array($user, $pw); -} - -/** - * True iff the operator is the canonical 'pi-star' account AND - * still using the factory default password 'raspberry'. - * - * Account scope is deliberately narrow: the requirement is to - * protect against drive-by auth using the well-known stock - * credentials. Operators who created their own usernames are - * out of scope (they made an active choice). - * - * Constant-time compare via hash_equals — defence in depth; the - * default password is publicly documented so timing isn't really - * an oracle, but it's the right idiom for password compares. - * - * @return bool - */ -function _pistar_default_password_in_use() -{ - list($user, $pw) = _pistar_get_basic_auth(); - if ($user !== 'pi-star' || $pw === '') { - return false; - } - return hash_equals('raspberry', $pw); -} - -/** - * The Pi's local interface subnets (IPv4 + IPv6). - * - * Read once per request from `ip -j addr show` (iproute2 JSON output; - * always present on Pi-Star). Cached in a static for repeated calls. - * - * @return array - */ -function _pistar_local_subnets() -{ - static $cached = null; - if ($cached !== null) { - return $cached; - } - $cached = array(); - - $out = array(); - $rc = 1; - exec('ip -j addr show 2>/dev/null', $out, $rc); - if ($rc !== 0 || empty($out)) { - return $cached; - } - $ifaces = json_decode(implode('', $out), true); - if (!is_array($ifaces)) { - return $cached; - } - foreach ($ifaces as $iface) { - if (empty($iface['addr_info']) || !is_array($iface['addr_info'])) { - continue; - } - foreach ($iface['addr_info'] as $a) { - if (empty($a['local']) || !isset($a['prefixlen'])) { - continue; - } - $cached[] = array( - 'ip' => (string)$a['local'], - 'prefix' => (int)$a['prefixlen'], - ); - } - } - return $cached; -} - -/** - * Family-aware bitmask subnet membership test. - * - * Handles IPv4, IPv6, and the IPv4-mapped IPv6 form (`::ffff:a.b.c.d`) - * that nginx may surface in REMOTE_ADDR when the listener is dual-stack. - * - * @param string $remote The address to test. - * @param string $netIp The subnet's network/anchor address. - * @param int $prefix Prefix length in bits (0..32 for IPv4, 0..128 for IPv6). - * - * @return bool - */ -function _pistar_ip_in_subnet($remote, $netIp, $prefix) -{ - $remoteBin = @inet_pton($remote); - $netBin = @inet_pton($netIp); - if ($remoteBin === false || $netBin === false) { - return false; - } - // Handle v4-mapped v6 (::ffff:1.2.3.4) when comparing against a - // bare v4 subnet — strip the 12-byte v4-mapped prefix. Mapping is - // one-directional by design: nginx surfaces REMOTE_ADDR in mapped - // form on dual-stack listeners while `ip -j addr show` reports the - // interface as bare v4, so the asymmetric strip is what the real - // topology produces. The reverse case (bare v4 client, mapped - // subnet) cannot occur in practice and falls through to "not a - // match" below. - if (strlen($remoteBin) === 16 && strlen($netBin) === 4 - && substr($remoteBin, 0, 12) === "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff") { - $remoteBin = substr($remoteBin, 12); - } - if (strlen($remoteBin) !== strlen($netBin)) { - // Different families and no compatible mapping — not in subnet. - return false; - } - $bits = strlen($remoteBin) * 8; - if ($prefix < 0 || $prefix > $bits) { - return false; - } - $bytesFull = intdiv($prefix, 8); - $bitsExtra = $prefix % 8; - if ($bytesFull > 0 - && substr($remoteBin, 0, $bytesFull) !== substr($netBin, 0, $bytesFull)) { - return false; - } - if ($bitsExtra > 0) { - $mask = chr((0xFF << (8 - $bitsExtra)) & 0xFF); - if ((substr($remoteBin, $bytesFull, 1) & $mask) - !== (substr($netBin, $bytesFull, 1) & $mask)) { - return false; - } - } - return true; -} - -/** - * Is REMOTE_ADDR in the same L3 subnet as ANY of the Pi's interfaces? - * - * Loopback (127.0.0.0/8 on v4, ::1/128 on v6) is treated as local — - * those addresses appear when an admin page is hit via the device - * itself or via a CLI test harness on the Pi. - * - * @return bool - */ -function _pistar_remote_is_local() -{ - $remote = isset($_SERVER['REMOTE_ADDR']) ? (string)$_SERVER['REMOTE_ADDR'] : ''; - if ($remote === '') { - return false; - } - foreach (_pistar_local_subnets() as $sub) { - if (_pistar_ip_in_subnet($remote, $sub['ip'], $sub['prefix'])) { - return true; - } - } - return false; -} - -/** - * Layer 2: redirect to the forced-change page when default password + - * remote client. Must be called BEFORE any output so header() works. - * - * Skips: - * - Public (non-/admin/) URLs — anonymous visitors don't get told - * the device is on default credentials. - * - The /admin/change_password_required.php page itself — would - * loop. - * - Pages reached during the setup-not-done flow (no mode marker - * file yet) — let the existing "No Mode Defined" handler in - * index.php drive the operator through configure.php first. - * - * @return void - */ -function pistar_warnings_enforce_redirect() -{ - $self = isset($_SERVER['PHP_SELF']) ? (string)$_SERVER['PHP_SELF'] : ''; - if (strpos($self, '/admin/') !== 0) { - return; - } - if ($self === '/admin/change_password_required.php') { - return; - } - // Long-running operational tools — let the operator finish what - // they're doing. The Layer-1 banner still appears at the top of - // these pages so the warning isn't suppressed; only the redirect - // is. update.php and expert/upgrade.php both poll a `?ajax` - // log-tail every 1 s; redirecting on those polls causes jQuery - // to follow the 302 and append the full change-password HTML - // into the page's #tail div, "flooding" the operator with copies - // of the change-password form. - if ($self === '/admin/update.php' - || $self === '/admin/expert/upgrade.php') { - return; - } - // Defence in depth: any GET that includes ?ajax skips the redirect. - // Catches AJAX log-tail / status-poll endpoints elsewhere in the - // dashboard (live_modem_log.php, expert/jitter_test.php, etc.) so - // a future poll-style page can't accidentally regress the same way. - // The initial GET that loaded the parent page already carried the - // banner — defaulting AJAX to "no redirect" is safe. - if (isset($_GET['ajax'])) { - return; - } - if (!file_exists('/etc/dstar-radio.mmdvmhost') - && !file_exists('/etc/dstar-radio.dstarrepeater')) { - return; - } - if (!_pistar_default_password_in_use()) { - return; - } - if (_pistar_remote_is_local()) { - return; - } - header('Location: /admin/change_password_required.php', true, 302); - exit; -} - -/** - * Render every applicable warning banner. Admin URLs only. - * - * Adding a new banner here? The body string is interpolated into the - * raw — pre-escape any dynamic content with htmlspecialchars() - * before passing it to _pistar_banner_emit(). Today's seven banners - * are all string literals so the issue does not arise. - * - * @return void - */ -function pistar_warnings_render() -{ - $self = isset($_SERVER['PHP_SELF']) ? (string)$_SERVER['PHP_SELF'] : ''; - if (strpos($self, '/admin/') !== 0) { - return; - } - - // Default-password banner FIRST — highest severity, most actionable. - if (_pistar_default_password_in_use()) { - _pistar_banner_emit( - 'Security Alert: Your dashboard is using the default password. ' - . 'Please change it now ' - . 'from the Configuration page.', - 'danger' - ); - } - - // Pi-Star release-derived banners. parse_ini_file() once per request. - $release = @parse_ini_file('/etc/pistar-release', true); - $version = is_array($release) && isset($release['Pi-Star']['Version']) - ? (string)$release['Pi-Star']['Version'] - : ''; - $hardware = is_array($release) && isset($release['Pi-Star']['Hardware']) - ? (string)$release['Pi-Star']['Hardware'] - : ''; - - if ($version !== '' && $hardware === 'RPi' - && version_compare($version, '4.1', '<')) { - _pistar_banner_emit( - 'Alert: You are running an outdated version of Pi-Star, please upgrade.
' - . 'New versions are available from here: ' - . 'http://www.pistar.uk/downloads/.', - 'warn' - ); - } - if ($version !== '' - && version_compare($version, '4.1.0', '>=') - && version_compare($version, '4.1.13', '<')) { - _pistar_banner_emit( - 'Alert: An upgrade to Pi-Star has been released, click here to upgrade now: ' - . 'Upgrade Pi-Star.', - 'warn' - ); - } - if ($version !== '' - && version_compare($version, '4.2.0', '>=') - && version_compare($version, '4.2.6', '<')) { - _pistar_banner_emit( - 'Alert: An upgrade to Pi-Star has been released, click here to upgrade now: ' - . 'Upgrade Pi-Star.', - 'warn' - ); - } - if ($version !== '' - && version_compare($version, '4.3.0', '>=') - && version_compare($version, '4.3.7', '<')) { - _pistar_banner_emit( - 'Alert: An upgrade to Pi-Star has been released, click here to upgrade now: ' - . 'Upgrade Pi-Star.', - 'warn' - ); - } - - // DMR public mode without ACL (loop risk). Was configure.php-only; - // now appears across the admin surface so the operator sees it - // regardless of which page they land on first. - if (file_exists('/etc/dstar-radio.mmdvmhost')) { - $mmdvm = @parse_ini_file('/etc/mmdvmhost', true); - if (is_array($mmdvm) - && isset($mmdvm['DMR']['Enable']) && $mmdvm['DMR']['Enable'] == 1 - && isset($mmdvm['DMR']['SelfOnly']) && $mmdvm['DMR']['SelfOnly'] == 0 - && isset($mmdvm['General']['Id']) - && strlen((string)$mmdvm['General']['Id']) >= 7 - && !isset($mmdvm['DMR']['WhiteList'])) { - _pistar_banner_emit( - 'Alert: You are running a hotspot in public mode without an access list for DMR, ' - . 'this setup *could* participate in network loops!', - 'warn' - ); - } - } - - // BM API v1 key (length-based heuristic, kept identical to the - // configure.php trigger this consolidates). - $bmKey = '/etc/bmapi.key'; - if (file_exists($bmKey)) { - $bm = @parse_ini_file($bmKey, true); - if (is_array($bm) && !empty($bm['key']['apikey']) - && strlen((string)$bm['key']['apikey']) <= 200) { - _pistar_banner_emit( - 'Alert: You have a BM API v1 Key, click here for the announcement: ' - . 'BM API Keys - Announcement.', - 'danger' - ); - } - } -} diff --git a/config/browserdetect.php b/config/browserdetect.php index 0304f88..0a3564a 100644 --- a/config/browserdetect.php +++ b/config/browserdetect.php @@ -1,35 +1,15 @@ ` - * tags wired up with media queries: `pistar-css.php` for desktop widths, - * `pistar-css-mini.php` for narrow / mobile widths. - * - * The big regex in this file is the standard "detectmobilebrowsers" - * UA list (https://detectmobilebrowsers.com/) and is intentionally not - * formatted — it's a single literal that must stay byte-identical to - * remain a valid match for the documented agent list. - * - * Included from the page by index.php / admin/index.php and - * the configure / power / update pages. - */ - -if (empty($_SERVER['HTTP_USER_AGENT'])) { - // No UA at all (curl, some CLIs, oddball clients): default to the - // desktop-vs-mobile width-based pair so behaviour matches a normal - // browser hitting the page. +if(empty($_SERVER['HTTP_USER_AGENT'])) { + print " \n"; + print " \n"; +} else { + $useragent=$_SERVER['HTTP_USER_AGENT']; + if (preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))) { + print " \n"; + print " \n"; + } else { print " \n"; print " \n"; -} else { - $useragent = $_SERVER['HTTP_USER_AGENT']; - if (preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))) { - // Mobile UA detected — bias toward the narrow-screen stylesheet. - print " \n"; - print " \n"; - } else { - // Desktop UA — width-based pair (same as the no-UA branch). - print " \n"; - print " \n"; - } + } } +?> diff --git a/config/config.php b/config/config.php index e431a7e..6fdbeee 100644 --- a/config/config.php +++ b/config/config.php @@ -1,52 +1,27 @@ diff --git a/config/config_writer.php b/config/config_writer.php deleted file mode 100644 index cf45298..0000000 --- a/config/config_writer.php +++ /dev/null @@ -1,570 +0,0 @@ -=` (column 0 — stricter than sed's "anywhere on line" - * pattern, which is actually the correct intent and avoids the - * classic substring-collision class of bug). If the key is absent, - * do nothing — same as sed. Append-if-missing would be a behaviour - * change for daemons with strict parsers and isn't safe without a - * per-file audit; defer to a later opt-in flag if needed. - * - * - **Atomic file replacement via `sudo install -m 644 -o root -g root`.** - * `cp` is not atomic — open + write + close on the destination - * leaves a window where the file is partially written. `install` - * uses rename(2) when src and dst share a filesystem; falls back to - * copy+chmod+chown when they don't (which is our case here — `/tmp` - * is tmpfs, the destination is on the SD card). The fallback is no - * less atomic than the existing `cp` pattern used elsewhere in this - * dashboard, and it sets mode/owner in one go. A future hardening - * pass could co-locate the staging file with the destination for - * true rename(2) atomicity. - * - * - **Hardcoded shell command literals.** `system()` is called with a - * fixed-shape command string; only fixed paths and `escapeshellarg()`- - * wrapped arguments are interpolated. PHP's `proc_open()` array form - * is PHP 7.4+ and this codebase targets PHP 7.0+, so we stay with - * `system()` plus `escapeshellarg()` instead. - * - * - **Whitespace preservation.** Existing files use `key=value` with - * no spaces around `=`. The helper preserves that exactly — it does - * NOT normalise existing files' formatting. Daemons in this stack - * parse their own configs with byte-precise matching; introducing - * spurious whitespace changes would risk breakage out of scope for - * this fix. - * - * - **Concurrent-edits.** Pi-Star is a single-operator embedded device - * in practice. The read-mutate-write window in commit() is wider - * than sed's, but two simultaneous configure.php POSTs are vanishingly - * rare on the target hardware. TODO: add file locking via flock() - * if this assumption ever stops holding. - */ - -/** - * Allow-list of paths the helper is permitted to write via the - * flat key=value editor. Any other path passed to - * `config_writer_stage_flat()` is rejected with an error_log() - * entry and a `false` return. - * - * Defined as a function (not a constant) so the file is safe to - * `require_once` multiple times under PHP 7.0 — array constants from - * `define()` work in 7.0 but `const` arrays at the file scope are - * 5.6+ and uniform-array-syntax limits make redefinition awkward. - * - * @return array - */ -function config_writer_allowed_paths() -{ - return array( - '/etc/ircddbgateway', - '/etc/dstarrepeater', - '/etc/timeserver', - '/etc/aprsgateway', - '/etc/mobilegps', - '/etc/starnetserver', - ); -} - -/** - * Allow-list of paths the helper is permitted to write via the - * privileged-flat editor (`config_writer_stage_privileged_flat()`). - * - * Same column-0 `key=value` semantics as the unprivileged flat - * editor, but the read step uses `sudo cat` so the helper can - * service files that are mode-600 root:root and therefore not - * readable by www-data. The destination is restored at mode 600 - * root:root via `sudo install`. Kept separate from the flat - * allowlist because the read path and the install mode differ. - * - * @return array - */ -function config_writer_allowed_paths_privileged_flat() -{ - return array( - '/root/.Remote Control', // note: literal space in filename - '/etc/hostapd/hostapd.conf', // contains wpa_passphrase=… ; mode 600 root:root - ); -} - -/** - * Allow-list of paths the helper is permitted to write via the - * PHP-statement editor (`config_writer_stage_php_string()`). - * - * These files are PHP source files included by the dashboard at - * runtime. Each contains one or more lines of the form - * `$varName='value';` at column 0. The PHP-statement editor - * rewrites the value with proper PHP-string escaping so the - * attacker-controlled bytes can never escape the single-quoted - * string literal — preventing PHP RCE via these files. - * - * Kept separate from the flat allow-list because the file shape - * and the editing semantics are different. A path that's writable - * under one editor is NOT automatically writable under the other. - * - * @return array - */ -function config_writer_allowed_paths_php_string() -{ - return array( - '/var/www/dashboard/config/language.php', - '/var/www/dashboard/config/ircddblocal.php', - ); -} - -/** - * Stage a single `key=value` edit against a flat config file. - * - * The edit is queued in process-local memory. Nothing touches disk - * until {@see config_writer_commit()} runs. Multiple stages against the - * same file accumulate; multiple stages of the same key in the same - * file overwrite each other (last write wins) and only the last is - * applied at commit time. - * - * @param string $path Absolute path. Must appear in - * {@see config_writer_allowed_paths()}. - * @param string $key The key name, e.g. `aprsHostname`. Must match - * `[A-Za-z_][A-Za-z0-9_]*` — defence in depth so - * a programming-error caller can't inject a - * regex/sed metachar via the key. - * @param string $value The new value. Must not contain NUL / CR / LF - * (those would break the line-oriented file - * format). All other bytes — including shell - * metachars like `"` `'` `;` `&` `$` — are stored - * verbatim, which is correct: the value is data, - * not a shell argument. - * - * @return bool True if staged. False if rejected (path not allow- - * listed, key malformed, or value contains NUL/CR/LF). - * On false, an error_log() entry is emitted. - */ -function config_writer_stage_flat($path, $key, $value) -{ - if (!in_array($path, config_writer_allowed_paths(), true)) { - error_log("config_writer: refusing to stage edit against non-allowlisted path '$path'"); - return false; - } - if (!preg_match('/\A[A-Za-z_][A-Za-z0-9_]*\z/', $key)) { - error_log("config_writer: refusing to stage malformed key '$key' for $path"); - return false; - } - if (preg_match('/[\x00\r\n]/', $value)) { - error_log("config_writer: refusing to stage value with NUL/CR/LF for $path:$key"); - return false; - } - - if (!isset($GLOBALS['__config_writer_stage'])) { - $GLOBALS['__config_writer_stage'] = array(); - } - if (!isset($GLOBALS['__config_writer_stage'][$path])) { - $GLOBALS['__config_writer_stage'][$path] = array(); - } - // Last write wins for repeated stages of the same key. - $GLOBALS['__config_writer_stage'][$path][$key] = $value; - return true; -} - -/** - * Stage a single PHP single-quoted string assignment edit. - * - * Targets PHP source files in - * {@see config_writer_allowed_paths_php_string()} that contain a - * line of the form `$varName='value';` at column 0. The first - * matching line is rewritten with the new value, properly escaped - * for a PHP single-quoted string literal — `\\` and `'` inside - * the value are escaped to `\\\\` and `\\'` respectively. All - * other bytes (including shell metachars `"` `;` `&` `$`) are - * stored verbatim — they are data inside a string literal, not - * code. This closes the PHP RCE class introduced by the previous - * `sudo sed -i` pattern, where attacker bytes could close the - * sed-emitted single-quote and inject arbitrary PHP statements. - * - * Like {@see config_writer_stage_flat()}, the edit is queued in - * memory until {@see config_writer_commit()} runs. - * - * @param string $path Absolute path. Must appear in - * {@see config_writer_allowed_paths_php_string()}. - * @param string $varName PHP variable name (no leading `$`). - * Must match `[A-Za-z_][A-Za-z0-9_]*`. - * @param string $value The new value to assign. Must not contain - * NUL/CR/LF (those would either break PHP - * parsing or break the line-oriented edit). - * - * @return bool True if staged. False if rejected. - */ -function config_writer_stage_php_string($path, $varName, $value) -{ - if (!in_array($path, config_writer_allowed_paths_php_string(), true)) { - error_log("config_writer: refusing PHP-string stage for non-allowlisted path '$path'"); - return false; - } - if (!preg_match('/\A[A-Za-z_][A-Za-z0-9_]*\z/', $varName)) { - error_log("config_writer: refusing malformed PHP var name '$varName' for $path"); - return false; - } - if (preg_match('/[\x00\r\n]/', $value)) { - error_log("config_writer: refusing PHP-string value with NUL/CR/LF for $path:\$$varName"); - return false; - } - - if (!isset($GLOBALS['__config_writer_stage_phpstr'])) { - $GLOBALS['__config_writer_stage_phpstr'] = array(); - } - if (!isset($GLOBALS['__config_writer_stage_phpstr'][$path])) { - $GLOBALS['__config_writer_stage_phpstr'][$path] = array(); - } - $GLOBALS['__config_writer_stage_phpstr'][$path][$varName] = $value; - return true; -} - -/** - * Stage a single `key=value` edit against a flat config file that - * lives under root-only permissions. - * - * Identical contract to {@see config_writer_stage_flat()} except the - * file is read via `sudo cat` instead of the PHP-side `file()` — - * because mode-600 root:root paths are not readable by www-data — - * and the destination is reinstalled at mode 600 root:root rather - * than 644. - * - * The only currently-allowlisted path is `/root/.Remote Control`, - * which holds the ircDDBGateway remote-control password and port. - * - * @param string $path Absolute path. Must appear in - * {@see config_writer_allowed_paths_privileged_flat()}. - * @param string $key Same key contract as the unprivileged flat - * editor. - * @param string $value Same value contract. - * - * @return bool True if staged. False if rejected. - */ -function config_writer_stage_privileged_flat($path, $key, $value) -{ - if (!in_array($path, config_writer_allowed_paths_privileged_flat(), true)) { - error_log("config_writer: refusing privileged-flat stage for non-allowlisted path '$path'"); - return false; - } - if (!preg_match('/\A[A-Za-z_][A-Za-z0-9_]*\z/', $key)) { - error_log("config_writer: refusing malformed privileged-flat key '$key' for $path"); - return false; - } - if (preg_match('/[\x00\r\n]/', $value)) { - error_log("config_writer: refusing privileged-flat value with NUL/CR/LF for $path:$key"); - return false; - } - - if (!isset($GLOBALS['__config_writer_stage_priv'])) { - $GLOBALS['__config_writer_stage_priv'] = array(); - } - if (!isset($GLOBALS['__config_writer_stage_priv'][$path])) { - $GLOBALS['__config_writer_stage_priv'][$path] = array(); - } - $GLOBALS['__config_writer_stage_priv'][$path][$key] = $value; - return true; -} - -/** - * Atomically install $newContent at $path with the given mode root:root. - * - * Internal helper shared by the flat and php-string commit paths. - * Returns null on success or a single-line diagnostic on failure. - * On failure the destination is left untouched and the temp file - * is unlinked. - * - * @param string $path Absolute destination path. - * @param string $newContent Full file content to install. - * - * @return string|null Error string, or null on success. - */ -function _config_writer_install_atomic($path, $newContent, $mode = '644') -{ - // Defence in depth — $mode is never attacker-controlled (the - // helper's commit() picks one of two hardcoded values), but we - // refuse anything outside the small expected set so a future - // typo can't inadvertently widen file permissions. - if ($mode !== '644' && $mode !== '600') { - return "config_writer: refusing invalid mode '$mode' for $path"; - } - $tmp = tempnam('/tmp', 'pistar_cw_'); - if ($tmp === false) { - return "config_writer: tempnam() failed for $path"; - } - // tempnam() creates the file mode 0600 on POSIX, but a non-default - // umask could in theory widen it. Force-narrow before writing — - // the temp content may be a freshly-set password. - @chmod($tmp, 0600); - if (file_put_contents($tmp, $newContent) === false) { - @unlink($tmp); - return "config_writer: file_put_contents() failed for $tmp; $path edits skipped"; - } - $cmd = 'sudo install -m ' . $mode . ' -o root -g root ' - . escapeshellarg($tmp) . ' ' - . escapeshellarg($path); - $rc = 0; - $out = array(); - exec($cmd . ' 2>&1', $out, $rc); - @unlink($tmp); - if ($rc !== 0) { - return "config_writer: install exit=$rc for $path: " . implode(' / ', $out); - } - return null; -} - -/** - * Apply every staged edit and clear the staging buffer. - * - * For each affected file: - * 1. Read the file into a line array. - * 2. For each staged `key => value`, find the FIRST line whose head - * is `key=` (column 0) and replace it with `key=value`. If the - * key is absent, the edit is silently skipped (matches sed's - * `c\` semantics). - * 3. Write the rebuilt content to a tempnam() in /tmp. - * 4. Atomically copy back via `sudo install -m 644 -o root -g root`. - * - * Wraps the per-file install calls in a single mount-rw / mount-ro - * pair so concurrent POSTs can't race on remount toggles. Callers - * that already manage their own mount cycle (e.g. configure.php's - * top-level POST handler, which keeps `/` rw across many edits) - * should pass `$manageMount = false` to skip the helper's own - * mount-rw/ro — otherwise the helper's mount-ro will prematurely - * close the caller's write window. - * - * @param bool $manageMount Whether commit() should issue its own - * `sudo mount -o remount,rw /` and - * `... remount,ro /` around the batch. - * Default true — safe for one-off callers. - * Pass false from inside an already-managed - * mount window. - * - * @return array Diagnostic strings — empty on full success. - * Non-empty entries describe per-file failures - * (read failure, file_put_contents failure, - * install non-zero exit). The caller decides - * whether to surface to the UI or just log. - */ -function config_writer_commit($manageMount = true) -{ - $errors = array(); - $flatStage = isset($GLOBALS['__config_writer_stage']) - ? $GLOBALS['__config_writer_stage'] - : array(); - $phpStrStage = isset($GLOBALS['__config_writer_stage_phpstr']) - ? $GLOBALS['__config_writer_stage_phpstr'] - : array(); - $privStage = isset($GLOBALS['__config_writer_stage_priv']) - ? $GLOBALS['__config_writer_stage_priv'] - : array(); - - if (empty($flatStage) && empty($phpStrStage) && empty($privStage)) { - return $errors; - } - - // Optional single mount-rw / batched-install / mount-ro envelope. - // When the caller already has `/` open rw (configure.php's POST - // handler does this for the duration of a save), we MUST NOT do - // our own mount-ro at the end — that would prematurely close the - // caller's window and break later writes (e.g. the timezone - // handler that runs after this commit). - if ($manageMount) { - system('sudo mount -o remount,rw /'); - } - - // Pass 1 — flat key=value edits. - foreach ($flatStage as $path => $kvPairs) { - if (!is_readable($path)) { - $errors[] = "config_writer: cannot read $path; edits skipped"; - error_log("config_writer: cannot read $path; " . count($kvPairs) . " edits skipped"); - continue; - } - $lines = file($path, FILE_IGNORE_NEW_LINES); - if ($lines === false) { - $errors[] = "config_writer: file() failed for $path; edits skipped"; - error_log("config_writer: file() failed for $path; " . count($kvPairs) . " edits skipped"); - continue; - } - - foreach ($kvPairs as $key => $value) { - $prefix = $key . '='; - $applied = false; - foreach ($lines as $i => $line) { - if (strpos($line, $prefix) === 0) { - $lines[$i] = $prefix . $value; - $applied = true; - break; - } - } - // Silent no-op when the key isn't present — matches the - // previous sed `c\` semantics. If the caller cares, log - // here. (Quiet by default to avoid filling the log on - // version-skew between the dashboard and the gateway - // configs.) - if (!$applied) { - error_log("config_writer: $path has no '$key=' line; edit skipped"); - } - } - - $err = _config_writer_install_atomic( - $path, - implode("\n", $lines) . "\n" - ); - if ($err !== null) { - $errors[] = $err; - error_log($err); - } - } - - // Pass 2 — PHP single-quoted string assignment edits. - foreach ($phpStrStage as $path => $varValuePairs) { - if (!is_readable($path)) { - $errors[] = "config_writer: cannot read $path; PHP-string edits skipped"; - error_log("config_writer: cannot read $path; " - . count($varValuePairs) . " PHP-string edits skipped"); - continue; - } - $lines = file($path, FILE_IGNORE_NEW_LINES); - if ($lines === false) { - $errors[] = "config_writer: file() failed for $path; PHP-string edits skipped"; - error_log("config_writer: file() failed for $path; " - . count($varValuePairs) . " PHP-string edits skipped"); - continue; - } - - foreach ($varValuePairs as $varName => $value) { - // Match column-0 `$varName` followed by optional whitespace - // then `=`. preg_quote is belt-and-braces — the var name is - // already validated to /^[A-Za-z_][A-Za-z0-9_]*$/ by - // config_writer_stage_php_string(). - $pattern = '/^\$' . preg_quote($varName, '/') . '\s*=/'; - $applied = false; - foreach ($lines as $i => $line) { - if (preg_match($pattern, $line)) { - // Escape value for a PHP single-quoted string - // literal: only `\` and `'` are special inside - // `'...'`. The two-char mask "\\'" tells - // addcslashes() to backslash-escape both: - // `\` → `\\` (first char of the mask) - // `'` → `\'` (second char of the mask) - // The result is parseable PHP that decodes back - // to the original $value bytes — so attacker - // bytes are stored as data, never executed. - $escaped = addcslashes($value, "\\'"); - $lines[$i] = '$' . $varName . "='" . $escaped . "';"; - $applied = true; - break; - } - } - if (!$applied) { - error_log("config_writer: $path has no \$$varName= line; PHP-string edit skipped"); - } - } - - $err = _config_writer_install_atomic( - $path, - implode("\n", $lines) . "\n" - ); - if ($err !== null) { - $errors[] = $err; - error_log($err); - } - } - - // Pass 3 — privileged flat key=value edits (root-only files). - // Same column-0 `key=` semantics as pass 1, but the read step - // uses `sudo cat` so we can service mode-600 root:root paths, - // and the install mode is 600 not 644. - foreach ($privStage as $path => $kvPairs) { - $rc = 0; - $out = array(); - // sudo -n: never prompt — fail loudly if sudoers ever changes. - // Output is the file content; stderr captured separately so a - // sudo / cat failure doesn't poison the parsed lines. - exec('sudo -n cat ' . escapeshellarg($path) . ' 2>/dev/null', - $out, $rc); - if ($rc !== 0) { - $errors[] = "config_writer: sudo cat exit=$rc for $path; privileged edits skipped"; - error_log("config_writer: sudo cat exit=$rc for $path; " - . count($kvPairs) . " privileged edits skipped"); - continue; - } - $lines = $out; - - foreach ($kvPairs as $key => $value) { - $prefix = $key . '='; - $applied = false; - foreach ($lines as $i => $line) { - if (strpos($line, $prefix) === 0) { - $lines[$i] = $prefix . $value; - $applied = true; - break; - } - } - if (!$applied) { - error_log("config_writer: $path has no '$key=' line; privileged edit skipped"); - } - } - - $err = _config_writer_install_atomic( - $path, - implode("\n", $lines) . "\n", - '600' - ); - if ($err !== null) { - $errors[] = $err; - error_log($err); - } - } - - if ($manageMount) { - system('sudo mount -o remount,ro /'); - } - - // Clear all stages so a subsequent commit() call doesn't - // re-apply already-applied edits. - $GLOBALS['__config_writer_stage'] = array(); - $GLOBALS['__config_writer_stage_phpstr'] = array(); - $GLOBALS['__config_writer_stage_priv'] = array(); - - return $errors; -} diff --git a/config/csrf.php b/config/csrf.php deleted file mode 100644 index 09a4901..0000000 --- a/config/csrf.php +++ /dev/null @@ -1,426 +0,0 @@ - string (64 hex chars; idempotent within a session) - * csrf_field() -> echoes a hidden tag for forms - * csrf_verify() -> dies with HTTP 403 if the POSTed token is missing - * or invalid; returns silently otherwise - * - * Usage - * ===== - * - * In a top-level GET-rendered page that contains a POST form: - * - * require_once $_SERVER['DOCUMENT_ROOT'] . '/config/csrf.php'; - * ... - *
- * - * ... - *
- * - * In the matching POST handler (top of the file, before any state - * change): - * - * require_once $_SERVER['DOCUMENT_ROOT'] . '/config/csrf.php'; - * if ($_SERVER['REQUEST_METHOD'] === 'POST') { - * csrf_verify(); - * } - * - * Design notes - * ============ - * - * - One token per session, reused across forms. Simpler retrofit - * than per-form tokens; no UX downside (the attacker still can't - * read the token, which is what matters). The token rotates - * when the session itself rotates (typically: browser closed, - * basic-auth re-prompted, or `session_regenerate_id()` called - * elsewhere). - * - * - Token = `bin2hex(random_bytes(32))` -> 64 hex chars (256 bits - * of entropy). `random_bytes()` is PHP 7.0+ and uses the - * OS CSPRNG (`/dev/urandom` on Linux). PHP 7.0 is this codebase's - * stated floor, so no fallback needed. - * - * - Verification uses `hash_equals()` (PHP 5.6+) for constant- - * time comparison. This is overkill for a hex-vs-hex comparison - * against a 256-bit secret, but costs nothing and removes any - * theoretical timing-leak class. - * - * - Failure mode (HTTP 403): write a minimal, self-contained HTML - * page rather than a JSON blob. The dashboard's forms post - * directly and the user lands on the response body in their - * browser — they need to understand what happened. - * - * - We deliberately do NOT call session_regenerate_id() on each - * request. Several existing pages (admin/update.php, - * admin/calibration.php, admin/live_modem_log.php) store - * log-tail offsets in $_SESSION across many AJAX requests; a - * mid-session ID rotation would lose those offsets and break - * the live log tails. - * - * - GET requests are NOT verified. CSRF protection only applies - * to state-changing requests, and the dashboard's idempotent - * read pages are POST-free by convention. - * - * - Session-cookie hardening. We set HttpOnly + SameSite=Lax on - * every issued PHPSESSID, and Secure conditionally when the - * request is HTTPS (via isHttps() in security_headers.php — - * covers direct TLS to nginx AND reverse-proxy / Cloudflare - * terminations that forward via X-Forwarded-Proto). See - * {@see _csrf_set_cookie_params()}. - */ - -require_once $_SERVER['DOCUMENT_ROOT'] . '/config/security_headers.php'; - -/** - * Configure the PHPSESSID cookie's flags for hardened delivery. - * - * Must be called BEFORE session_start(); has no effect once the - * session is active. Sets: - * - * HttpOnly — always. Blocks document.cookie access from JS, so - * a future XSS in any rendered page can't read the - * session ID. Defence in depth alongside the input - * escaping work in the rest of the security pass. - * - * SameSite=Lax — always. Browser stops sending the cookie on - * cross-site subresource fetches and cross-site POSTs; - * top-level navigation (clicking a bookmark, following - * a same-origin redirect) still carries it, so UX - * doesn't change. Belt-and-braces with the existing - * CSRF-token check. - * - * Secure — conditional on isHttps(). UNCONDITIONALLY setting - * Secure would invalidate the cookie for the (large) - * population of operators on plain-HTTP LAN access - * and silently break CSRF protection. isHttps() also - * returns true for X-Forwarded-Proto: https — so - * operators behind Cloudflare / a reverse proxy / - * Tailscale Funnel get the right Secure flag even - * though nginx itself only sees plain HTTP. - * - * Trust caveat: an attacker who can talk directly - * to nginx on port 80 (bypassing the proxy) could - * spoof X-Forwarded-Proto and trick the dashboard - * into setting Secure on their own session. The - * consequence is the spoofer's cookie won't replay - * over plain HTTP — a self-DoS, not an escalation. - * - * PHP version handling. The samesite option was added to - * session_set_cookie_params() in PHP 7.3 (the array form). On - * 7.0..7.2 we fall back to the well-known path-suffix kludge: - * appending `; SameSite=Lax` to the path argument. PHP doesn't - * validate the path string — it concatenates verbatim into the - * Set-Cookie header — and browsers parse `path=/; SameSite=Lax` - * correctly because `;` terminates the path attribute. The - * codebase floor is PHP 7.0; the production runtime is PHP 8.2. - * - * @return void - */ -function _csrf_set_cookie_params() -{ - $secure = function_exists('isHttps') ? isHttps() : false; - if (PHP_VERSION_ID >= 70300) { - // Modern array form. Available since PHP 7.3. - @session_set_cookie_params(array( - 'lifetime' => 0, - 'path' => '/', - 'domain' => '', - 'secure' => $secure, - 'httponly' => true, - 'samesite' => 'Lax', - )); - } else { - // PHP 7.0..7.2: no native samesite support. The path-suffix - // kludge is the documented workaround — see PHP RFC for - // 7.3's array form, where this is acknowledged as the - // pre-7.3 idiom. lifetime/path/domain/secure/httponly here - // mirror the array values above. - @session_set_cookie_params(0, '/; SameSite=Lax', '', $secure, true); - } -} - -/** - * Ensure a session is started. Idempotent. - * - * Several dashboard pages already call `session_start()` for their - * own state (log offsets, etc.), so this primitive must coexist - * gracefully with prior `session_start()` calls. PHP_SESSION_ACTIVE - * is the canonical guard introduced in PHP 5.4. - */ -function csrf_session_start() -{ - if (session_status() !== PHP_SESSION_ACTIVE) { - // Pi-Star ships with `session.gc_probability=0` AND - // /var/lib/php/sessions mounted as a 64KB tmpfs (per - // /etc/fstab in the OS image). With CSRF, every dashboard - // visit creates a session file, and without automatic GC - // those accumulate until reboot — at which point the tmpfs - // fills (~15 sessions) and session_start() starts failing - // with "No space left on device", silently breaking CSRF. - // - // Force GC at session-start time by bumping the probability - // ratio to 1/1. PHP runs GC itself during session_start when - // (gc_probability / gc_divisor) > random — at 1/1 that's - // every call, but only for THIS request's session_start. - // Cost: a tmpfs `glob` + a few `unlink`s, microseconds. - // The @-suppression handles hosts that disallow ini_set on - // these keys; failure just means we fall back to PHP's - // default behaviour, same as before this fix. - // - // session_gc() (PHP 7.1+) would be cleaner but the codebase - // targets PHP 7.0. ini_set works on every supported version. - if ((int)ini_get('session.gc_probability') === 0) { - @ini_set('session.gc_probability', '1'); - @ini_set('session.gc_divisor', '1'); - } - // gc_maxlifetime is intentionally NOT overridden here — we - // defer to Pi-Star's stock /etc/php/*/fpm/php.ini value - // (1440 s, matching PHP's own default). The dashboard's - // AJAX-refreshing panels (lh.php, repeaterinfo.php, the - // bm_links / tgif_links partials, etc.) do not load csrf.php, - // so they don't update the session file's mtime — meaning the - // session counts as "idle" from the moment csrf_verify() last - // ran on a top-level page load, even while the dashboard is - // visibly active in the operator's tab. Anything shorter than - // ~24 min would routinely 403 BM-manager / TGIF-manager / - // configure.php POSTs whenever the operator left the dashboard - // tab open between page loads. tmpfs containment is the - // pre-emptive prune below, not maxlifetime. - // - // Pi-Star's /var/lib/php/sessions tmpfs is sized 64 KB (per - // /etc/fstab in the OS image) — about 15 session files at - // a 4 KB tmpfs block each. csrf.php is only loaded behind - // basic auth on /admin/*, so the only session-creators are - // authenticated operators (whose browsers reuse one cookie = - // one session) and tooling that hits the dashboard with - // fresh cookie jars per request. The latter has filled the - // tmpfs in practice; once full, session_start() fails with - // "No space left on device" and CSRF silently breaks for - // the operator — they get a 403 on the next form submit - // because $_SESSION['csrf_token'] could not be persisted. - // - // Belt-and-braces safety net: cap the session directory at - // 12 files BEFORE session_start() tries to write a new one. - // GC alone won't help here because a burst of fresh-cookie - // requests can fill the 64 KB tmpfs faster than gc_maxlifetime - // expires anything. This pre-emptive prune deletes the - // oldest sess_* files until 12 remain, leaving ~3 slots of - // headroom under the ~15-file tmpfs cap. - // - // Best-effort: any failure here (permissions, missing dir, - // glob/unlink errors) is silently ignored — session_start() - // will still try and either succeed or fall through to the - // existing failure-logging path below. Worst case for an - // evicted session is an operator gets a 403 on the next - // form submit and a page reload re-issues a token, which - // is far better than the disk-full failure this guards - // against. - $sessSaveDir = (string)@ini_get('session.save_path'); - if ($sessSaveDir !== '') { - $sessFiles = @glob($sessSaveDir . '/sess_*'); - if (is_array($sessFiles) && count($sessFiles) > 12) { - usort($sessFiles, function ($a, $b) { - return (int)@filemtime($a) - (int)@filemtime($b); - }); - $sessExcess = count($sessFiles) - 12; - for ($i = 0; $i < $sessExcess; $i++) { - @unlink($sessFiles[$i]); - } - } - } - // Harden the PHPSESSID cookie flags BEFORE session_start() - // emits the Set-Cookie header. See _csrf_set_cookie_params() - // for the per-flag rationale. - _csrf_set_cookie_params(); - // Suppress notices about headers already sent — some - // dashboard pages emit output before this is reached. - // The session won't be usable in that scenario, but - // failing closed (csrf_verify rejects the POST) is the - // correct outcome. Log the underlying cause so a future - // maintainer who accidentally reorders requires above an - // echo can see why their POSTs started 403'ing. - if (@session_start() === false) { - error_log('csrf_session_start: session_start() failed ' - . '(headers already sent? require_once order?)'); - } - } -} - -/** - * Return the session's CSRF token, issuing a fresh one on first - * call within a session. - * - * @return string 64-character hex string. - */ -function csrf_token() -{ - csrf_session_start(); - if (empty($_SESSION['csrf_token']) || !is_string($_SESSION['csrf_token'])) { - $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); - } - return $_SESSION['csrf_token']; -} - -/** - * Echo a hidden form input carrying the CSRF token. - * - * Place INSIDE the `
` element, before the submit button. - * Output is htmlspecialchars-safe: a hex string never contains - * any character that needs escaping, but we encode anyway as a - * defence against future changes to the token format. - * - * For sites that build form HTML into a string variable rather - * than echoing inline, see {@see csrf_field_html()}. - */ -function csrf_field() -{ - echo csrf_field_html(); -} - -/** - * Return a hidden form input carrying the CSRF token, as a - * string. Useful for code that accumulates form HTML into a - * `$output` variable (e.g. wifi.php's wpa_conf form) where an - * `echo` mid-expression doesn't compose. - * - * @return string The hidden-input HTML. - */ -function csrf_field_html() -{ - $tok = htmlspecialchars(csrf_token(), ENT_QUOTES, 'UTF-8'); - return ''; -} - -/** - * Verify the POSTed CSRF token. On mismatch, emit HTTP 403 and exit. - * - * Call this from EVERY state-changing POST handler before any side - * effect (file write, system call, session mutation, etc.). It is - * a no-op for GET / HEAD / OPTIONS requests — those are read-only - * by convention in this dashboard. - * - * The function does not return on failure: it sets the response - * code, prints a minimal HTML error page, and calls exit(). - */ -function csrf_verify() -{ - // Bootstrap the session up front, even on GET, so the - // Set-Cookie header gets emitted before any HTML output. - // csrf_field() (called inside the page's tags) is - // lazy and may not run until well after output has started, - // so without an early csrf_verify() call sites that don't - // already have their own pre-output session_start() (most - // pages — power.php is the exception) never get a session - // cookie. Without a cookie the GET-issued token has no way - // to reach the POST handler. - // - // Pages should call csrf_verify() near the top of the file, - // BEFORE any output. On GET it bootstraps the session and - // returns; on POST it bootstraps, validates, and either - // returns silently or emits 403 + exit(). - csrf_session_start(); - - if (!isset($_SERVER['REQUEST_METHOD']) || - $_SERVER['REQUEST_METHOD'] !== 'POST') { - // Only POST is gated — GET pages render the token via - // csrf_field() and don't need verification. - return; - } - - $expected = isset($_SESSION['csrf_token']) ? $_SESSION['csrf_token'] : ''; - $supplied = isset($_POST['csrf_token']) ? $_POST['csrf_token'] : ''; - - // Distinguish "session has no token" from "session has a token - // and the supplied one is wrong". The former is almost always a - // benign expired-session POST (operator left the dashboard tab - // open past gc_maxlifetime, then clicked submit) and shouldn't - // throw the alarmist 403 page at them. Redirect 303 to the same - // URL — the browser switches to GET, the page re-renders fresh - // (forms that pre-populate from disk come back filled in; the - // session_start() in csrf_session_start() issues a new token), - // and the operator's submit retry just works. - // - // This is safe against forgery because a real attacker would be - // sending against an ACTIVE operator session whose - // $_SESSION['csrf_token'] is non-empty — that path stays on the - // strict 403 below. The only thing the redirect "lets through" - // is a fresh form render, which any GET would also serve. - if ($expected === '' || !is_string($expected) || strlen($expected) !== 64) { - $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/admin/'; - // Defence in depth: REQUEST_URI is typically same-origin - // already, but force a relative path so a crafted Host or - // proxy can't turn this into an open redirect. - $uri = '/' . ltrim(preg_replace('#^https?://[^/]*#i', '', $uri), '/'); - header('Location: ' . $uri, true, 303); - header('Cache-Control: no-store'); - exit; - } - - // Reject only when the session actually had a token but the - // supplied one is missing or doesn't match — that IS a forgery. - if (!is_string($supplied) || strlen($supplied) !== 64 || - !hash_equals($expected, $supplied)) { - // Best-effort log line for the operator. The remote IP is - // typically a LAN address but worth recording in case a - // rogue device is fingerprinted by repeated 403s. - $remote = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '?'; - $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '?'; - error_log("csrf_verify: rejected POST from $remote to $uri"); - - http_response_code(403); - header('Content-Type: text/html; charset=utf-8'); - // Don't pollute browser history with this response. - header('Cache-Control: no-store'); - // English-only by design: the dashboard's lang/ system - // requires config/language.php, which reads /etc/pistar-release - // and the gateway configs. Pulling that whole stack into an - // error path that only fires under attack is disproportionate. - echo '' - . '403 Forbidden' - . '

403 Forbidden

' - . '

This request did not include a valid CSRF token. ' - . 'If you reached this page by clicking a link from another site, ' - . 'that other site may have been trying to perform an action on ' - . 'your behalf without your consent.

' - . '

If you reached this page by submitting a form on the ' - . 'dashboard, your session may have expired. Reload the page ' - . 'and try again.

' - . ''; - exit; - } - - // Token verified — strip it from $_POST so downstream handlers - // that iterate $_POST (e.g. fulledit_bmapikey.php and - // fulledit_dapnetapi.php's INI writers, which treat each top- - // level POST key as an [INI section]) don't accidentally write - // a stray `[csrf token]` block into /etc/. Without this, - // every successful submit on those editors prepended an empty - // `[csrf token]` section to the saved config and rendered a - // ghost table titled "csrf_token" on the response page. - // Centralising the unset here means every current and future - // POST handler is immune without needing to remember the dance. - unset($_POST['csrf_token']); -} diff --git a/config/ircddblocal.php b/config/ircddblocal.php index b36ad1f..4d9d682 100644 --- a/config/ircddblocal.php +++ b/config/ircddblocal.php @@ -1,28 +1,15 @@ + diff --git a/config/security_headers.php b/config/security_headers.php deleted file mode 100644 index 15b608e..0000000 --- a/config/security_headers.php +++ /dev/null @@ -1,193 +0,0 @@ - diff --git a/css/index.php b/css/index.php index 702d3d1..e69de29 100644 --- a/css/index.php +++ b/css/index.php @@ -1,3 +0,0 @@ - +:root { + --page-bg: #; + --content-bg: #; + --accent: #; + --accent-dark: #; + --accent-light: #; + --accent-text: #; + --banner-drop: #; + --table-head-drop: #; + --content-text: #; + --table-even: #; + --table-odd: #; + --sidebar-bg: #111827; + --sidebar-bg-2: #0b1120; + --sidebar-text: #cbd5e1; + --sidebar-text-dim: #94a3b8; + --sidebar-card-bg: rgba(255,255,255,0.05); + --sidebar-card-strong-bg: rgba(255,255,255,0.09); + --radius: 12px; + --radius-sm: 8px; + --card-border: rgba(15,23,42,0.07); + --shadow-card: 0 1px 2px rgba(15,23,42,0.04), 0 10px 28px -14px rgba(15,23,42,0.16); +} + +html, body { + margin: 0; + padding: 0; +} + +/* Small screens: the rail collapses into a top bar (no fixed sidebar) */ .container { width: 100%; text-align: left; margin: auto; - background : #; - border-radius: 10px 10px 10px 10px; - -moz-border-radius: 10px 10px 10px 10px; - -webkit-border-radius: 10px 10px 10px 10px; - -khtml-border-radius: 10px 10px 10px 10px; - -ms-border-radius: 10px 10px 10px 10px; - box-shadow: 3px 3px 3px #707070; + background: var(--page-bg); + border-radius: 0; + box-shadow: none; + overflow: visible; } body, font { - font: 12px verdana,arial,sans-serif; + font: 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; color: #ffffff; } .header { - background : #; - text-decoration : none; - color : #; - font-family : verdana, arial, sans-serif; - text-align : left; - padding : 5px 0px 5px 0px; - border-radius: 10px 10px 0 0; - -moz-border-radius: 10px 10px 0px 0px; - -webkit-border-radius: 10px 10px 0px 0px; - -khtml-border-radius: 10px 10px 0px 0px; - -ms-border-radius: 10px 10px 0px 0px; - } + position: static; + width: auto; + background: linear-gradient(180deg, var(--sidebar-bg), var(--sidebar-bg-2)); + color: var(--sidebar-text); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + padding: 16px 14px; + box-sizing: border-box; +} +.header h1 { + font-size: 1.05em; + line-height: 1.3; + color: #ffffff; + text-shadow: none; + text-align: left; + margin: 0 0 4px 0; + padding: 0; + font-weight: 700; +} + +.header > div[style*="font-size: 8px"] { + float: none !important; + text-align: left !important; + color: var(--sidebar-text-dim) !important; + font-size: 10.5px !important; + padding: 0 !important; + margin: 0 0 10px 0; +} + +.header p { + font-size: 0; + margin: 6px 0; + padding: 0; + text-align: left !important; + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 2px; +} + +.header p a, .header p a:link, .header p a:visited { + display: inline-block; + font-size: 13px; + font-weight: 500; + color: var(--sidebar-text) !important; + padding: 8px 10px; + border-radius: 8px; + transition: background 0.15s ease, color 0.15s ease; +} + +.header p a:hover { + background: rgba(255,255,255,0.08); + color: #ffffff !important; +} + +.header p a.active { + background: var(--accent); + color: var(--accent-text) !important; + font-weight: 700; +} + +.header p b { + font-size: 11px; + color: var(--sidebar-text-dim); + display: block; + width: 100%; + margin: 8px 0 2px 2px; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +/* On narrow screens the widgets no longer live in a side column - they + become a full-width panel stacked under the top bar, laid out as a + two-column grid of compact status chips instead of skinny stacked rows. */ .nav { - display: none; - float : left; - margin : 0; - padding : 3px 3px 3px 3px; - width : 160px; - background : #242d31; - font-weight : normal; - min-height : 100%; + display: block; + float: none; + box-sizing: border-box; + margin: 0; + padding: 14px; + width: 100%; + background: linear-gradient(180deg, var(--sidebar-bg), var(--sidebar-bg-2)); + font-weight: normal; + min-height: 0; +} + +.nav table { + width: 100%; + margin: 0 0 12px 0; + border-collapse: separate; + border-spacing: 4px; + table-layout: fixed; + white-space: normal; +} + +.nav table th[colspan] { + background: transparent; + color: var(--sidebar-text-dim); + text-align: left; + text-transform: uppercase; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.06em; + padding: 10px 2px 6px 2px; + border: none; +} + +.nav table:first-child th[colspan] { + padding-top: 0; +} + +.nav table th:not([colspan]) { + background: var(--sidebar-card-bg); + color: var(--sidebar-text-dim); + text-align: left; + font-size: 10.5px; + font-weight: 700; + padding: 7px 8px; + border: none; + border-radius: var(--radius-sm); + width: 30%; +} + +.nav table td { + color: var(--sidebar-text); + background: var(--sidebar-card-bg); + font-size: 11px; + font-weight: 600; + padding: 7px 8px; + border: none; + border-radius: var(--radius-sm); +} + +.nav table td[style*="fff"] { + background: var(--sidebar-card-strong-bg) !important; + color: var(--sidebar-text) !important; +} + +.nav table tr:nth-child(even), +.nav table tr:nth-child(odd) { + background: transparent; +} + +.nav table a { color: #ffffff; font-weight: 700; } + +#lastHerd, #localTxs, #Pages, #sysInfo, +#refLinks, #cssConnects, #lh, #localTx, #bmConnects, #tgifConnects { + margin: 14px; + background: var(--content-bg); + border: 1px solid var(--card-border); + border-radius: var(--radius); + box-shadow: var(--shadow-card); + padding: 14px 14px 18px 14px; + box-sizing: border-box; + overflow-x: auto; +} + +#lastHerd > b, #localTxs > b, #Pages > b, #sysInfo > b, +#refLinks > b, #cssConnects > b, #lh > b, #localTx > b, #bmConnects > b, #tgifConnects > b { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + font-weight: 700; + color: var(--content-text); + margin: 0 0 12px 0; + padding-bottom: 10px; + border-bottom: 1px solid var(--card-border); +} + +#lastHerd > b::before, #localTxs > b::before, #Pages > b::before, #sysInfo > b::before, +#refLinks > b::before, #cssConnects > b::before, #lh > b::before, #localTx > b::before, #bmConnects > b::before, #tgifConnects > b::before { + content: ""; + width: 8px; + height: 8px; + border-radius: 2px; + background: var(--accent); + flex: none; } .content { - padding : 5px 5px 5px 5px; - color : #; - background : #; - text-align: center; + padding: 6px 0 5px 0; + color: var(--content-text); + background: var(--page-bg); + text-align: left; font-size: 1.4em; } .contentwide { - padding: 5px 5px 5px 5px; - color: #; - background: #; + padding: 16px; + color: var(--content-text); + background: var(--page-bg); text-align: center; font-size: 1.4em; } .contentwide h2 { - color: #; - font: 1em verdana,arial,sans-serif; - text-align: center; - font-weight: bold; - padding: 0px; - margin: 0px; + color: var(--content-text); + font: 600 1em -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + padding: 0 0 8px 10px; + margin: 24px 0 10px 0; + border-left: 4px solid var(--accent); + border-bottom: 1px solid rgba(0,0,0,0.08); +} + +.contentwide h2:first-child { + margin-top: 0; +} + +/* Inline "Alert: ..." banners used across the dashboard (config warnings etc.) */ +.alert-banner-table { + margin: 0 0 16px 0 !important; + width: 100% !important; +} + +.alert-banner-table, .alert-banner-table tr { + background: transparent !important; +} + +.alert-cell { + text-align: left !important; + border-radius: 8px; + padding: 12px 16px !important; + font-weight: 500; + border: 1px solid transparent; +} + +.alert-warning { + background: #fffbeb; + color: #92400e; + border-color: #fde68a; +} + +.alert-danger { + background: #fef2f2; + color: #b91c1c; + border-color: #fecaca; +} + +.alert-warning a, .alert-danger a { + color: inherit; + text-decoration: underline; +} + +/* Settings-card system (mirrors pistar-css.php) - this was missing from the + mobile stylesheet entirely, so every config/editor page rendered as + unstyled plain divs below the 830px breakpoint. Rows stack by default + here since there's no room for the desktop's label+control row. */ +.settings-card { + background: var(--content-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0,0,0,0.04); + padding: 4px 16px; + margin: 0 0 20px 0; + text-align: left; +} + +.settings-card > b:first-child { + display: flex; + align-items: center; + gap: 8px; + font-size: 14px; + font-weight: 700; + color: var(--content-text); + margin: 14px 0 12px 0; + padding-bottom: 10px; + border-bottom: 1px solid var(--card-border); +} + +.settings-card > b:first-child::before { + content: ""; + width: 8px; + height: 8px; + border-radius: 2px; + background: var(--accent); + flex: none; +} + +.field-row { + display: flex; + flex-direction: column; + align-items: flex-start; + row-gap: 6px; + padding: 12px 0; + border-bottom: 1px solid rgba(0,0,0,0.06); +} + +.field-row:last-child { + border-bottom: none; +} + +.field-label, .field-row > div:first-child { + flex: 0 0 auto; + max-width: none; + font-weight: 500; + font-size: 13px; + color: var(--content-text); + text-align: left; +} + +.field-control, .field-row > div:not(:first-child) { + flex: 1 1 auto; + width: 100%; + box-sizing: border-box; + text-align: left; + color: var(--content-text); + font-size: 13px; +} + +.field-control input[type="text"], .field-control input[type="password"], .field-control input[type="number"], +.field-row input[type="text"], .field-row input[type="password"], .field-row input[type="number"] { + width: 100%; + box-sizing: border-box; + padding: 6px 8px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-control select, .field-row select { + max-width: 100%; + padding: 5px 6px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-note { + font-weight: 400; + font-size: 12.5px; + color: #6b7280; +} + +/* Big icon action buttons (power page, reboot/shutdown) */ +.action-tiles { + display: flex; + flex-wrap: wrap; + gap: 12px; + padding: 14px; +} + +.action-tile { + flex: 1 1 45%; + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + padding: 18px 12px; + background: var(--page-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 10px; + cursor: pointer; + font: 500 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + color: var(--content-text); +} + +.action-tile img { + width: 40px; + height: 40px; +} + +.action-tile-upload { + cursor: default; +} + +.action-tile-upload input[type="file"] { + max-width: 100%; + font-size: 11px; +} + +/* Calibration tool control panels */ +.cal-grid { + display: flex; + flex-wrap: wrap; + gap: 14px; + align-items: flex-start; +} + +.cal-panel { + flex: 1 1 100%; + margin: 0; +} + +.cal-panel table { + width: 100%; +} + +.cal-btn-row { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 0; + flex-wrap: wrap; +} + +/* Raw config-file editors (expert "Full Edit" pages) */ +.raw-editor { + width: 100%; + min-height: 360px; + box-sizing: border-box; + background: #10141a; + color: #d1d5db; + border: 1px solid rgba(0,0,0,0.15); + border-radius: 8px; + padding: 10px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + font-size: 12px; + line-height: 1.5; +} + +.power-status { + background: #10141a; + color: #3ce87a; + border-radius: 8px; + padding: 16px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + line-height: 1.6; +} + +.field-actions { + display: flex; + justify-content: center; + align-items: center; + padding: 18px 0 22px 0; +} + +.field-actions input[type="button"], .field-actions input[type="submit"] { + background: var(--accent); + color: var(--accent-text); + border: none; + padding: 11px 40px; + font-size: 14px; + font-weight: 700; + letter-spacing: 0.02em; + border-radius: 999px; + box-shadow: 0 2px 6px rgba(15,23,42,0.16), 0 8px 20px -8px rgba(15,23,42,0.28); + cursor: pointer; +} + +.field-actions input[type="button"]:active, .field-actions input[type="submit"]:active { + filter: brightness(0.97); } .footer { - background : #; - text-decoration : none; - color : #; - font-family : verdana, arial, sans-serif; - font-size : 9px; - text-align : center; - padding : 10px 0 10px 0; - border-radius: 0 0 10px 10px; - -moz-border-radius: 0px 0px 10px 10px; - -webkit-border-radius: 0px 0px 10px 10px; - -khtml-border-radius: 0px 0px 10px 10px; - -ms-border-radius: 0px 0px 10px 10px; - clear : both; + background: transparent; + text-decoration: none; + color: #6b7280; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + font-size: 10.5px; + text-align: left; + padding: 14px 16px 20px 16px; + border-top: 1px solid rgba(0,0,0,0.07); + clear: both; +} + +.footer a { + color: var(--accent) !important; } #tail { height: 450px; - width: 805px; + width: 100%; overflow-y: scroll; overflow-x: scroll; - color: #00ff00; - background: #000000; + color: #3ce87a; + background: #10141a; + border-radius: 8px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + box-sizing: border-box; +} + +#tail::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +#tail::-webkit-scrollbar-track { + background: #10141a; +} + +#tail::-webkit-scrollbar-thumb { + background: rgba(60, 232, 122, 0.35); + border-radius: 6px; } table { @@ -156,57 +589,72 @@ table { padding-right: 0px; padding-top: 0px; padding-bottom: 0px; - border-collapse:collapse; - border-color: #000000; - border-style: solid; - border-spacing: 4px; - border-width: 2px; + border-collapse: collapse; + border: none; text-decoration: none; color: #ffffff; - background: #000000; - font-family: verdana,arial,sans-serif; + background: transparent; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; width: 100%; white-space: nowrap; } table th { - font-family: "Lucidia Console",Monaco,monospace; - text-shadow: 1px 1px #; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-shadow: none; text-decoration: none; - background: #; - border: 1px solid #c0c0c0; + background: transparent; + color: var(--content-text); + text-transform: uppercase; + font-size: 10.5px; + font-weight: 700; + letter-spacing: 0.03em; + padding: 9px 10px; + border: none; + border-bottom: 2px solid var(--accent); } table tr:nth-child(even) { - background: #; + background: var(--table-even); } table tr:nth-child(odd) { - background: #; + background: var(--table-odd); } table td { - color: #000000; - font-family: "Lucidia Console",Monaco,monospace; + color: var(--content-text); + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; text-decoration: none; - border: 1px solid #000000; + padding: 7px 10px; + border: none; + border-bottom: 1px solid var(--card-border); overflow-x: hidden; } +table tr:last-child td { + border-bottom: none; +} + body { - background: #; - color: #000000; + background: var(--page-bg); + color: var(--content-text); } a { text-decoration:none; - } a:link, a:visited { text-decoration: none; - color: #0000e0; + color: var(--accent); font-weight: normal; + transition: color 0.15s ease; +} + +a:hover { + color: var(--accent-dark); + text-decoration: underline; } a.tooltip, a.tooltip:link, a.tooltip:visited, a.tooltip:active { @@ -238,10 +686,13 @@ a.tooltip:hover span { width: 200px; z-index: 100; color: #000000; - border:1px solid #000000; + border: none; + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); background: #f7f7f7; - font: 12px Verdana, sans-serif; + font: 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; text-align: left; + overflow: hidden; } a.tooltip span b { @@ -250,12 +701,12 @@ a.tooltip span b { display: block; color: #000000; margin: 0; - padding: 0; + padding: 4px 8px; font-size: 12px; font-weight: bold; border: 0px; - border-bottom: 1px solid black; - background: #d0d0d0; + border-bottom: 1px solid rgba(0,0,0,0.15); + background: #e2e2e2; } a.tooltip2, a.tooltip2:link, a.tooltip2:visited, a.tooltip2:active { @@ -289,10 +740,13 @@ a.tooltip2:hover span { width: 200px; z-index: 100; color: #000000; - border:1px solid #000000; + border: none; + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); background: #f7f7f7; - font: 12px Verdana, sans-serif; + font: 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; text-align: left; + overflow: hidden; } a.tooltip2 span b { @@ -301,12 +755,12 @@ a.tooltip2 span b { display: block; color: #000000; margin: 0; - padding: 0; + padding: 4px 8px; font-size: 12px; font-weight: bold; border: 0px; - border-bottom: 1px solid black; - background: #d0d0d0; + border-bottom: 1px solid rgba(0,0,0,0.15); + background: #e2e2e2; } ul { @@ -327,7 +781,8 @@ ul li a { float:left; color: #999; cursor: pointer; - font: 900 14px/22px "Arial", Helvetica, sans-serif; + font: 900 14px/22px -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + transition: color 0.15s ease; } ul li a span { @@ -347,7 +802,7 @@ ul.mmenu li a.current span, ul.mmenu li a:hover span { } h1 { - text-shadow: 2px 2px #; + text-shadow: 1px 1px 2px rgba(0,0,0,0.35); text-align: center; } @@ -402,12 +857,35 @@ input.toggle-round-flat + label:after { } input.toggle-round-flat:checked + label { - background-color: #; + background-color: var(--accent); } input.toggle-round-flat:checked + label:after { margin-left: 14px; - background-color: #; + background-color: var(--accent); +} + +/* Gentle, geometry-neutral polish for form controls (no size/layout changes) */ +input[type="text"], input[type="password"], input[type="number"], input[type="email"], select, textarea { + border-radius: 4px; + transition: box-shadow 0.15s ease, border-color 0.15s ease; +} + +input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus, input[type="email"]:focus, select:focus, textarea:focus { + outline: none; + box-shadow: 0 0 0 3px rgba(79,70,229,0.18); + border-color: var(--accent); +} + +input[type="submit"], input[type="button"], button { + cursor: pointer; + border-radius: 4px; + transition: filter 0.15s ease, box-shadow 0.15s ease; +} + +input[type="submit"]:hover, input[type="button"]:hover, button:hover { + filter: brightness(1.06); + box-shadow: 0 1px 6px rgba(0,0,0,0.25); } /* Tame Firefox Buttons */ @@ -417,7 +895,7 @@ input.toggle-round-flat:checked + label:after { margin : 0; padding : 0; border-width : 1px; - font : 12px verdana,arial,sans-serif; + font : 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; } input[type="button"], button, input[type="submit"] { padding : 0px 3px 0px 3px; diff --git a/css/pistar-css.php b/css/pistar-css.php index 7fba766..fc13710 100644 --- a/css/pistar-css.php +++ b/css/pistar-css.php @@ -1,145 +1,727 @@ -.container { - width: 820px; - text-align: left; - margin: auto; - border-radius: 10px 10px 10px 10px; - -moz-border-radius: 10px 10px 10px 10px; - -webkit-border-radius: 10px 10px 10px 10px; - -khtml-border-radius: 10px 10px 10px 10px; - -ms-border-radius: 10px 10px 10px 10px; - box-shadow: 3px 3px 3px #707070; - background : #; +:root { + --page-bg: #; + --content-bg: #; + --accent: #; + --accent-dark: #; + --accent-light: #; + --accent-text: #; + --banner-drop: #; + --table-head-drop: #; + --content-text: #; + --table-even: #; + --table-odd: #; + --sidebar-width: 250px; + --nav-width: 226px; + --sidebar-bg: #111827; + --sidebar-bg-2: #0b1120; + --sidebar-text: #cbd5e1; + --sidebar-text-dim: #94a3b8; + --sidebar-card-bg: rgba(255,255,255,0.05); + --sidebar-card-strong-bg: rgba(255,255,255,0.09); + --radius: 12px; + --radius-sm: 8px; + --card-border: rgba(15,23,42,0.07); + --shadow-card: 0 1px 2px rgba(15,23,42,0.04), 0 10px 28px -14px rgba(15,23,42,0.16); +} + +* { + -webkit-font-smoothing: antialiased; +} + +html, body { + margin: 0; + padding: 0; } body, font { - font: 12px verdana,arial,sans-serif; + font: 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; color: #ffffff; } -.header { - background : #; - text-decoration : none; - color : #; - font-family : verdana, arial, sans-serif; - text-align : left; - padding : 5px 0px 5px 0px; - border-radius: 10px 10px 0 0; - -moz-border-radius: 10px 10px 0px 0px; - -webkit-border-radius: 10px 10px 0px 0px; - -khtml-border-radius: 10px 10px 0px 0px; - -ms-border-radius: 10px 10px 0px 0px; - } - -.nav { - float : left; - margin : 0; - padding : 3px 3px 3px 3px; - width : 160px; - background : #242d31; - font-weight : normal; - min-height : 100%; +body { + background: var(--page-bg); + color: var(--content-text); } +/* Outer shell: the sidebar (.header) is fixed, everything else lives in this column */ +.container { + width: auto; + margin: 0 0 0 var(--sidebar-width); + min-height: 100vh; + text-align: left; + background: var(--page-bg); + box-shadow: none; + border-radius: 0; + overflow: visible; +} + +/* The left-hand navigation rail. Same markup as before (title + link list), + just presented as a fixed vertical sidebar instead of a top banner. */ +.header { + position: fixed; + top: 0; + left: 0; + bottom: 0; + width: var(--sidebar-width); + background: linear-gradient(180deg, var(--sidebar-bg), var(--sidebar-bg-2)); + color: var(--sidebar-text); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + padding: 22px 16px 16px 16px; + overflow-y: auto; + z-index: 200; + display: flex; + flex-direction: column; + box-sizing: border-box; +} + +.header h1 { + font-size: 1.15em; + line-height: 1.3; + color: #ffffff; + text-shadow: none; + text-align: left; + margin: 0 0 4px 0; + padding: 0; + font-weight: 700; +} + +.header > div[style*="font-size: 8px"] { + float: none !important; + text-align: left !important; + color: var(--sidebar-text-dim) !important; + font-size: 10.5px !important; + padding: 0 !important; + margin: 0 0 14px 0; +} + +.header p { + /* The historical pipe-separated link list. Collapsing the literal " | " + separators to zero size turns it into a clean vertical nav without + touching the markup that generates it. */ + font-size: 0; + margin: 6px 0; + padding: 0; + text-align: left !important; + display: flex; + flex-direction: column; + gap: 2px; +} + +.header p a, .header p a:link, .header p a:visited { + display: block; + font-size: 13px; + font-weight: 500; + color: var(--sidebar-text) !important; + padding: 9px 10px; + border-radius: 8px; + transition: background 0.15s ease, color 0.15s ease; +} + +.header p a:hover { + background: rgba(255,255,255,0.08); + color: #ffffff !important; +} + +.header p a.active { + background: var(--accent); + color: var(--accent-text) !important; + font-weight: 700; +} + +.header p b { + font-size: 11px; + color: var(--sidebar-text-dim); + display: block; + margin: 10px 0 2px 2px; + text-transform: uppercase; + letter-spacing: 0.04em; +} + +/* Second half of the sidebar: live status widgets (Modes/Network/Radio Info). + Same dark surface as .header so the two columns read as one continuous + rail, even though .nav scrolls with the page instead of staying fixed. */ +/* Wraps .nav + .content so both stretch to the same height - without this, + the dark .nav background only reached as far down as its own widgets and + left a visible step where the fixed .header strip kept going but .nav + stopped short. */ +.dashboard-row { + display: flex; + align-items: stretch; +} + +.nav { + flex: none; + display: flex; + flex-direction: column; + justify-content: center; + box-sizing: border-box; + margin: 0; + padding: 20px 14px; + width: var(--nav-width); + background: linear-gradient(180deg, var(--sidebar-bg), var(--sidebar-bg-2)); + font-weight: normal; +} + +.nav table { + width: 100%; + margin: 0 0 16px 0; + border-collapse: separate; + border-spacing: 4px; + table-layout: fixed; + white-space: normal; +} + +/* Section titles ("Modes Enabled", "Radio Info", "DMR Master"...) */ +.nav table th[colspan] { + background: transparent; + color: var(--sidebar-text-dim); + text-align: left; + text-transform: uppercase; + font-size: 10px; + font-weight: 700; + letter-spacing: 0.06em; + padding: 12px 2px 6px 2px; + border: none; +} + +.nav table:first-child th[colspan] { + padding-top: 0; +} + +/* Field-label cells (Trx / Tx / Rx / RPT1 / DMR ID ...) */ +.nav table th:not([colspan]) { + background: var(--sidebar-card-bg); + color: var(--sidebar-text-dim); + text-align: left; + font-size: 10.5px; + font-weight: 700; + letter-spacing: 0.02em; + padding: 7px 8px; + border: none; + border-radius: var(--radius-sm); + width: 30%; +} + +/* Value / status cells. Anything with an inline background (status colour + pills from showMode()/repeaterinfo.php) keeps that colour untouched - + we only add shape. Explicit inline white backgrounds are swapped for a + theme-matching dark surface so they don't glow against the sidebar. */ +.nav table td { + color: var(--sidebar-text); + background: var(--sidebar-card-bg); + font-size: 11px; + font-weight: 600; + padding: 7px 8px; + border: none; + border-radius: var(--radius-sm); + text-overflow: ellipsis; + overflow: hidden; +} + +.nav table td[style*="fff"] { + background: var(--sidebar-card-strong-bg) !important; + color: var(--sidebar-text) !important; +} + +.nav table tr:nth-child(even), +.nav table tr:nth-child(odd) { + background: transparent; +} + +.nav table a { color: #ffffff; font-weight: 700; } +.nav table a:hover { color: var(--accent-light); } + .content { - margin : 0 0 0 166px; - padding : 1px 5px 5px 5px; - color : #; - background : #; - text-align: center; + flex: 1 1 auto; + min-width: 0; + margin: 0 0 0 20px; + padding: 24px 28px 28px 28px; + color: var(--content-text); + background: var(--page-bg); + text-align: left; } .contentwide { - padding: 5px 5px 5px 5px; - color: #; - background: #; + padding: 24px 28px; + color: var(--content-text); + background: var(--page-bg); text-align: center; } .contentwide h2 { - color: #; - font: 1em verdana,arial,sans-serif; - text-align: center; - font-weight: bold; - padding: 0px; - margin: 0px; + color: var(--content-text); + font: 600 1.15em -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + padding: 0 0 10px 14px; + margin: 32px 0 14px 0; + border-left: 4px solid var(--accent); + border-bottom: 1px solid rgba(0,0,0,0.08); } +.contentwide h2:first-child { + margin-top: 0; +} + +.contentwide h3 { + color: var(--content-text); + font: 600 0.95em -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-align: left; + margin: 20px 0 8px 2px; +} + +.contentwide h3:first-of-type { + margin-top: 4px; +} + +/* Usage meter (RAM/disk bars on the SysInfo page) */ +.meter { + position: relative; + width: 100%; + max-width: 420px; + height: 20px; + background: var(--page-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 10px; + overflow: hidden; +} + +.meter-bar { + height: 100%; + background: linear-gradient(90deg, var(--accent-light), var(--accent)); +} + +.meter-label { + position: absolute; + top: 0; + left: 10px; + line-height: 20px; + font-size: 11.5px; + font-weight: 600; + color: var(--content-text); +} + +/* Inline "Alert: ..." banners used across the dashboard (config warnings etc.) */ +.alert-banner-table { + margin: 0 0 16px 0 !important; + width: 100% !important; +} + +.alert-banner-table, .alert-banner-table tr { + background: transparent !important; +} + +.alert-cell { + text-align: left !important; + border-radius: 8px; + padding: 12px 16px !important; + font-weight: 500; + border: 1px solid transparent; +} + +.alert-warning { + background: #fffbeb; + color: #92400e; + border-color: #fde68a; +} + +.alert-danger { + background: #fef2f2; + color: #b91c1c; + border-color: #fecaca; +} + +.alert-warning a, .alert-danger a { + color: inherit; + text-decoration: underline; +} .footer { - background : #; - text-decoration : none; - color : #; - font-family : verdana, arial, sans-serif; - font-size : 9px; - text-align : center; - padding : 10px 0 10px 0; - border-radius: 0 0 10px 10px; - -moz-border-radius: 0px 0px 10px 10px; - -webkit-border-radius: 0px 0px 10px 10px; - -khtml-border-radius: 0px 0px 10px 10px; - -ms-border-radius: 0px 0px 10px 10px; - clear : both; + background: transparent; + text-decoration: none; + color: #6b7280; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + font-size: 10.5px; + text-align: left; + padding: 16px 28px 24px 28px; + border-top: 1px solid rgba(0,0,0,0.07); + clear: both; +} + +.footer a { + color: var(--accent) !important; +} + +/* Modern settings form: replaces the old table-based "Setting | Value" rows. + .settings-card wraps a section's fields; .field-row is one label+control pair. */ +.settings-card { + background: var(--content-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0,0,0,0.04); + padding: 4px 20px; + margin: 0 0 28px 0; + text-align: left; +} + +/* Legacy fragments open with a bare Title before their content - + give it the same accent-dot heading treatment as the dashboard cards, + wherever it shows up, without having to touch every include site. */ +.settings-card > b:first-child { + display: flex; + align-items: center; + gap: 9px; + font-size: 15px; + font-weight: 700; + color: var(--content-text); + margin: 16px 0 14px 0; + padding-bottom: 12px; + border-bottom: 1px solid var(--card-border); +} + +.settings-card > b:first-child::before { + content: ""; + width: 9px; + height: 9px; + border-radius: 3px; + background: var(--accent); + flex: none; +} + +.field-row { + display: flex; + align-items: center; + flex-wrap: wrap; + column-gap: 24px; + row-gap: 6px; + padding: 13px 0; + border-bottom: 1px solid rgba(0,0,0,0.06); +} + +.field-row:last-child { + border-bottom: none; +} + +.field-label { + flex: 0 0 260px; + max-width: 260px; + font-weight: 500; + font-size: 13px; + color: var(--content-text); + text-align: left; +} + +.field-control { + flex: 1 1 320px; + text-align: left; + color: var(--content-text); + font-size: 13px; +} + +.field-control input[type="text"], .field-control input[type="password"], .field-control input[type="number"] { + padding: 5px 8px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-control select { + padding: 4px 6px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-actions { + display: flex; + justify-content: center; + align-items: center; + padding: 20px 0 24px 0; +} + +.field-actions input[type="button"], .field-actions input[type="submit"] { + background: var(--accent); + color: var(--accent-text); + border: none; + padding: 12px 48px; + font-size: 14px; + font-weight: 700; + letter-spacing: 0.02em; + border-radius: 999px; + box-shadow: 0 2px 6px rgba(15,23,42,0.16), 0 8px 20px -8px rgba(15,23,42,0.28); + cursor: pointer; + transition: filter 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease; +} + +.field-actions input[type="button"]:hover, .field-actions input[type="submit"]:hover { + filter: brightness(1.08); + box-shadow: 0 4px 10px rgba(15,23,42,0.2), 0 10px 24px -8px rgba(15,23,42,0.32); + transform: translateY(-1px); +} + +.field-actions input[type="button"]:active, .field-actions input[type="submit"]:active { + transform: translateY(0); + filter: brightness(0.97); +} + +.field-note { + font-weight: 400; + font-size: 12.5px; + color: #6b7280; + flex: 1 1 100% !important; + max-width: none !important; +} + +/* Big icon action buttons (power page, reboot/shutdown) */ +.action-tiles { + display: flex; + gap: 16px; + padding: 20px; +} + +.action-tile { + flex: 1 1 0; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; + padding: 24px 16px; + background: var(--page-bg); + border: 1px solid rgba(0,0,0,0.08); + border-radius: 10px; + cursor: pointer; + font: 500 14px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + color: var(--content-text); + transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease; +} + +.action-tile:hover { + border-color: var(--accent); + box-shadow: 0 4px 12px rgba(0,0,0,0.08); + transform: translateY(-1px); +} + +.action-tile img { + width: 48px; + height: 48px; +} + +.action-tile-upload { + cursor: default; +} + +.action-tile-upload input[type="file"] { + max-width: 100%; + font-size: 12px; +} + +.action-tile-upload button { + margin-top: 4px; +} + +/* Calibration tool control panels */ +.cal-grid { + display: flex; + flex-wrap: wrap; + gap: 16px; + align-items: flex-start; +} + +.cal-panel { + flex: 1 1 220px; + margin: 0; +} + +.cal-panel h3 { + margin-top: 0; +} + +.cal-panel table { + width: 100%; +} + +.cal-btn-row { + display: flex; + align-items: center; + gap: 10px; + padding: 6px 0; +} + +/* Raw config-file editors (expert "Full Edit" pages) */ +.raw-editor { + width: 100%; + min-height: 480px; + box-sizing: border-box; + background: #10141a; + color: #d1d5db; + border: 1px solid rgba(0,0,0,0.15); + border-radius: 8px; + padding: 12px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + font-size: 12.5px; + line-height: 1.5; +} + +.power-status { + background: #10141a; + color: #3ce87a; + border-radius: 8px; + padding: 20px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + line-height: 1.7; +} + +/* Positional fallback for field-rows whose cells weren't given explicit + .field-label/.field-control classes (converted straight from table rows): + first direct child reads as the label, the rest as the control area. */ +.field-row > div:first-child { + flex: 0 0 260px; + max-width: 260px; + font-weight: 500; + font-size: 13px; + text-align: left; +} + +.field-row > div:not(:first-child) { + flex: 1 1 280px; + text-align: left; + font-size: 13px; +} + +.field-row input[type="text"], .field-row input[type="password"], .field-row input[type="number"] { + padding: 5px 8px; + border: 1px solid rgba(0,0,0,0.18); +} + +.field-row select { + padding: 4px 6px; + border: 1px solid rgba(0,0,0,0.18); +} + +@media (max-width: 780px) { + .field-row { + flex-direction: column; + align-items: flex-start; + } + .field-label, .field-row > div:first-child { + flex: 0 0 auto; + max-width: none; + } } #tail { height: 450px; - width: 805px; + width: 100%; + max-width: 805px; overflow-y: scroll; overflow-x: scroll; - color: #00ff00; - background: #000000; + color: #3ce87a; + background: #10141a; + border-radius: 8px; + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; + box-sizing: border-box; +} + +#tail::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +#tail::-webkit-scrollbar-track { + background: #10141a; +} + +#tail::-webkit-scrollbar-thumb { + background: rgba(60, 232, 122, 0.35); + border-radius: 6px; +} + +/* Dashboard widget panels: the Gateway/Local RF Activity tables (and the + POCSAG Pages list) get promoted from bare Title+ into real + cards, without touching the PHP that generates them. */ +#lastHerd, #localTxs, #Pages, #sysInfo, +#refLinks, #cssConnects, #lh, #localTx, #bmConnects, #tgifConnects { + width: 100%; + margin: 0 0 20px 0; + background: var(--content-bg); + border: 1px solid var(--card-border); + border-radius: var(--radius); + box-shadow: var(--shadow-card); + padding: 18px 22px 22px 22px; + box-sizing: border-box; + overflow-x: auto; +} + +#lastHerd > b, #localTxs > b, #Pages > b, #sysInfo > b, +#refLinks > b, #cssConnects > b, #lh > b, #localTx > b, #bmConnects > b, #tgifConnects > b { + display: flex; + align-items: center; + gap: 9px; + font-size: 15px; + font-weight: 700; + color: var(--content-text); + margin: 0 0 14px 0; + padding-bottom: 12px; + border-bottom: 1px solid var(--card-border); +} + +#lastHerd > b::before, #localTxs > b::before, #Pages > b::before, #sysInfo > b::before, +#refLinks > b::before, #cssConnects > b::before, #lh > b::before, #localTx > b::before, #bmConnects > b::before, #tgifConnects > b::before { + content: ""; + width: 9px; + height: 9px; + border-radius: 3px; + background: var(--accent); + flex: none; } table { @@ -150,56 +732,70 @@ table { padding-right: 0px; padding-top: 0px; padding-bottom: 0px; - border-collapse:collapse; - border-color: #000000; - border-style: solid; - border-spacing: 4px; - border-width: 2px; + border-collapse: collapse; + border: none; text-decoration: none; color: #ffffff; - background: #000000; - font-family: verdana,arial,sans-serif; + background: transparent; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; width: 100%; white-space: nowrap; } table th { - font-family: "Lucidia Console",Monaco,monospace; - text-shadow: 1px 1px #; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + text-shadow: none; text-decoration: none; - background: #; - border: 1px solid #c0c0c0; + background: transparent; + color: var(--content-text); + text-transform: uppercase; + font-size: 11px; + font-weight: 700; + letter-spacing: 0.04em; + padding: 10px 12px; + border: none; + border-bottom: 2px solid var(--accent); } table tr:nth-child(even) { - background: #; + background: var(--table-even); } table tr:nth-child(odd) { - background: #; + background: var(--table-odd); } table td { - color: #000000; - font-family: "Lucidia Console",Monaco,monospace; + color: var(--content-text); + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace; text-decoration: none; - border: 1px solid #000000; + padding: 8px 12px; + border: none; + border-bottom: 1px solid var(--card-border); } -body { - background: #; - color: #000000; +table tr:last-child td { + border-bottom: none; +} + +.content table tr:hover td, .contentwide table tr:hover td { + background: rgba(15,23,42,0.045); } a { text-decoration:none; - } a:link, a:visited { text-decoration: none; - color: #0000e0; + color: var(--accent); font-weight: normal; + transition: color 0.15s ease; +} + +a:hover { + color: var(--accent-dark); + text-decoration: underline; } a.tooltip, a.tooltip:link, a.tooltip:visited, a.tooltip:active { @@ -230,11 +826,14 @@ a.tooltip:hover span { left: 0; z-index: 100; color: #000000; - border:1px solid #000000; + border: none; + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); background: #f7f7f7; - font: 12px Verdana, sans-serif; + font: 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; text-align: left; white-space: nowrap; + overflow: hidden; } th:last-child a.tooltip:hover span { @@ -248,12 +847,12 @@ a.tooltip span b { display: block; color: #000000; margin: 0; - padding: 0; + padding: 4px 8px; font-size: 12px; font-weight: bold; border: 0px; - border-bottom: 1px solid black; - background: #d0d0d0; + border-bottom: 1px solid rgba(0,0,0,0.15); + background: #e2e2e2; } a.tooltip2, a.tooltip2:link, a.tooltip2:visited, a.tooltip2:active { @@ -287,11 +886,14 @@ a.tooltip2:hover span { width: 202px; z-index: 100; color: #000000; - border:1px solid #000000; + border: none; + border-radius: 6px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); background: #f7f7f7; - font: 12px Verdana, sans-serif; + font: 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; text-align: left; white-space: normal; + overflow: hidden; } a.tooltip2 span b { @@ -300,12 +902,12 @@ a.tooltip2 span b { display: block; color: #000000; margin: 0; - padding: 0; + padding: 4px 8px; font-size: 12px; font-weight: bold; border: 0px; - border-bottom: 1px solid black; - background: #d0d0d0; + border-bottom: 1px solid rgba(0,0,0,0.15); + background: #e2e2e2; } ul { @@ -326,7 +928,8 @@ ul li a { float:left; color: #999; cursor: pointer; - font: 900 14px/22px "Arial", Helvetica, sans-serif; + font: 900 14px/22px -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + transition: color 0.15s ease; } ul li a span { @@ -346,7 +949,7 @@ ul.mmenu li a.current span, ul.mmenu li a:hover span { } h1 { - text-shadow: 2px 2px #; + text-shadow: 1px 1px 2px rgba(0,0,0,0.35); text-align: center; } @@ -401,12 +1004,35 @@ input.toggle-round-flat + label:after { } input.toggle-round-flat:checked + label { - background-color: #; + background-color: var(--accent); } input.toggle-round-flat:checked + label:after { margin-left: 14px; - background-color: #; + background-color: var(--accent); +} + +/* Gentle, geometry-neutral polish for form controls (no size/layout changes) */ +input[type="text"], input[type="password"], input[type="number"], input[type="email"], select, textarea { + border-radius: 4px; + transition: box-shadow 0.15s ease, border-color 0.15s ease; +} + +input[type="text"]:focus, input[type="password"]:focus, input[type="number"]:focus, input[type="email"]:focus, select:focus, textarea:focus { + outline: none; + box-shadow: 0 0 0 3px rgba(79,70,229,0.18); + border-color: var(--accent); +} + +input[type="submit"], input[type="button"], button { + cursor: pointer; + border-radius: 4px; + transition: filter 0.15s ease, box-shadow 0.15s ease; +} + +input[type="submit"]:hover, input[type="button"]:hover, button:hover { + filter: brightness(1.06); + box-shadow: 0 1px 6px rgba(0,0,0,0.25); } /* Tame Firefox Buttons */ @@ -416,7 +1042,7 @@ input.toggle-round-flat:checked + label:after { margin : 0; padding : 0; border-width : 1px; - font : 12px verdana,arial,sans-serif; + font : 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; } input[type="button"], button, input[type="submit"] { padding : 0px 3px 0px 3px; @@ -435,6 +1061,34 @@ input.toggle-round-flat:checked + label:after { clear: both; } +/* Collapse the fixed sidebar into a top bar on narrow viewports */ +@media (max-width: 780px) { + .header { + position: static; + width: auto; + height: auto; + flex-direction: row; + flex-wrap: wrap; + align-items: center; + } + .header p { + flex-direction: row; + flex-wrap: wrap; + } + .container { + margin-left: 0; + } + .dashboard-row { + flex-direction: column; + } + .nav { + width: auto; + } + .content { + margin-left: 0; + } +} + /* Aria CSS Here [role="checkbox"] { padding:5px; diff --git a/dstarrepeater/active_reflector_links.php b/dstarrepeater/active_reflector_links.php index 0d12b59..ea1faa8 100644 --- a/dstarrepeater/active_reflector_links.php +++ b/dstarrepeater/active_reflector_links.php @@ -1,33 +1,5 @@ - 1) { $ci = 0; } - print ""; - $tr = 1; - $module = $configs[$param]; - $rcall = sprintf("%-7.7s%-1.1s",$MYCALL,$module); - $param="repeaterCall" . $i; - if(isset($configs[$param])) { $rptrcall=sprintf("%-7.7s%-1.1s",$configs[$param],$module); } else { $rptrcall = $rcall;} - print ""; - $param="reflector" . $i; - if(isset($configs[$param])) { print ""; } else { print "";} - $param="atStartup" . $i; - if($configs[$param] == 1){print ""; } else { print ""; } - $param="reconnect" . $i; - if(isset($configs[$param])) { $t = $configs[$param]; } else { $t = 0; } - if($t > 12){ $t = 12; } - print ""; - $j=0; - if ($linkLog = @fopen($linkLogPath,'r')) { - while ($linkLine = fgets($linkLog)) { - //$statimg = ""; - $statimg = "Down"; + $param="repeaterBand" . $i; + if((isset($configs[$param])) && strlen($configs[$param]) == 1) { + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + $tr = 1; + $module = $configs[$param]; + $rcall = sprintf("%-7.7s%-1.1s",$MYCALL,$module); + $param="repeaterCall" . $i; + if(isset($configs[$param])) { $rptrcall=sprintf("%-7.7s%-1.1s",$configs[$param],$module); } else { $rptrcall = $rcall;} + print ""; + $param="reflector" . $i; + if(isset($configs[$param])) { print ""; } else { print "";} + $param="atStartup" . $i; + if($configs[$param] == 1){print ""; } else { print ""; } + $param="reconnect" . $i; + if(isset($configs[$param])) { $t = $configs[$param]; } else { $t = 0; } + if($t > 12){ $t = 12; } + print ""; + $j=0; + if ($linkLog = fopen($linkLogPath,'r')) { + while ($linkLine = fgets($linkLog)) { + //$statimg = ""; + $statimg = "Down"; $linkDate = " "; $protocol = " "; $linkType = " "; @@ -96,83 +68,83 @@ $MYCALL=strtoupper($callsign); // 2012-10-12 17:15:45: DCS link - Type: Repeater Rptr: DB0LJ B Refl: DCS001 L Dir: Outgoing // 2012-10-12 17:56:10: DCS link - Type: Repeater Rptr: DB0RPL B Refl: DCS015 B Dir: Outgoing if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*Rptr: (.{8}).*Refl: (.{8}).*Dir: Outgoing$/',$linkLine,$linx) > 0){ - $statimg = "Up"; - $linkDate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); + $statimg = "Up"; + $linkDate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); $protocol = $linx[2][0]; $linkType = $linx[3][0]; $linkRptr = $linx[4][0]; $linkRefl = $linx[5][0]; - if($linkRptr == $rptrcall){ - print ""; - print ""; - print ""; - print ""; - $utc_time = $linkDate; - $utc_tz = new DateTimeZone('UTC'); - $local_tz = new DateTimeZone(date_default_timezone_get ()); - $dt = new DateTime($utc_time, $utc_tz); - $dt->setTimeZone($local_tz); - $local_time = $dt->format('H:i:s M jS'); - print ""; - print "\n"; - $tr = 0; - } - } - } - fclose($linkLog); - } + if($linkRptr == $rptrcall){ + print ""; + print ""; + print ""; + print ""; + $utc_time = $linkDate; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + print ""; + print "\n"; + $tr = 0; + } + } + } + fclose($linkLog); + } - if ($tr == 1){ - print"\n"; - } + if ($tr == 1){ + print"\n"; + } // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 // 2012-05-08 21:16:31: DExtra link - Type: Repeater Rptr: DB0LJ A Refl: DB0MYK B Dir: Incoming // 2012-05-08 21:16:31: DPlus link - Type: Dongle User: W1CDG H Dir: Incoming - if ($linkLog = @fopen($linkLogPath,'r')) { - while ($linkLine = fgets($linkLog)) { - $statimg = "Down"; + if ($linkLog = fopen($linkLogPath,'r')) { + while ($linkLine = fgets($linkLog)) { + $statimg = "Down"; $linkDate = " "; $protocol = " "; $linkType = " "; $linkRptr = " "; $linkRefl = " "; if(preg_match_all('/^(.{19}).*(D[A-Za-z]*).*Type: ([A-Za-z]*).*Rptr: (.{8}).*Refl: (.{8}).*Dir: Incoming$/',$linkLine,$linx) > 0){ - $statimg = "Up"; - $linkDate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); + $statimg = "Up"; + $linkDate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); $protocol = $linx[2][0]; $linkType = $linx[3][0]; $linkRptr = $linx[4][0]; $linkRefl = $linx[5][0]; - if($linkRptr == $rptrcall){ - $ci++; - if($ci > 1) { $ci = 0; } - print ""; - print ""; - print ""; - print ""; - print ""; - print ""; - print ""; - $utc_time = $linkDate; - $utc_tz = new DateTimeZone('UTC'); - $local_tz = new DateTimeZone(date_default_timezone_get ()); - $dt = new DateTime($utc_time, $utc_tz); - $dt->setTimeZone($local_tz); - $local_time = $dt->format('H:i:s M jS'); - print ""; - print "\n"; - //$tr = 0; - } - } - } - fclose($linkLog); - } + if($linkRptr == $rptrcall){ + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + print ""; + $utc_time = $linkDate; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + print ""; + print "\n"; + //$tr = 0; + } + } + } + fclose($linkLog); + } // 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122 // 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901 // 2012-05-08 21:16:31: DExtra link - Type: Repeater Rptr: DB0LJ A Refl: DB0MYK B Dir: Incoming // 2012-05-08 21:16:31: DPlus link - Type: Dongle User: W1CDG H Dir: Incoming - if ($linkLog = @fopen($linkLogPath,'r')) { + if ($linkLog = fopen($linkLogPath,'r')) { while ($linkLine = fgets($linkLog)) { $statimg = "Down"; $linkDate = " "; @@ -188,7 +160,7 @@ $MYCALL=strtoupper($callsign); $linkRptr = $linx[4][0]; $ci++; if($ci > 1) { $ci = 0; } - print ""; + print ""; print ""; print ""; print ""; @@ -207,8 +179,8 @@ $MYCALL=strtoupper($callsign); } fclose($linkLog); } - // End - } + // End + } } ?> diff --git a/dstarrepeater/active_starnet_groups.php b/dstarrepeater/active_starnet_groups.php index ad99f5b..102c01e 100644 --- a/dstarrepeater/active_starnet_groups.php +++ b/dstarrepeater/active_starnet_groups.php @@ -1,29 +1,5 @@ - from - * StarNet group " line. We treat the log as the - * authoritative state: an "Adding" entry inserts; a "Removing" - * entry unsets. The final $groupsx map then holds current members. - * - * No security_headers call — it's a sub-sub-partial. Flagged for the - * security pass. - */ - - -require_once($_SERVER['DOCUMENT_ROOT'] . '/config/security_headers.php'); -setSecurityHeaders(); - -include_once $_SERVER['DOCUMENT_ROOT'].'/config/ircddblocal.php'; -include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code + 1) { $ci = 0; } - print ""; - print ""; - $param="starNetLogoff" . $i; - if(isset($configs[$param])){ $output = str_replace(' ', ' ', substr($configs[$param],0,8)); print "";} else { print"";} - $param="starNetInfo" . $i; - if(isset($configs[$param])){ print "";} else { print"";} - $param="starNetUserTimeout" . $i; - if(isset($configs[$param])){ print "";} else { print"";} - $param="starNetGroupTimeout" . $i; - if(isset($configs[$param])){ print "";} else { print"";} - print "\n"; - } + $param="starNetCallsign" . $i; + if(isset($configs[$param])) { + $gname = $configs[$param]; + $stngrp[$gname] = $i; + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + print ""; + $param="starNetLogoff" . $i; + if(isset($configs[$param])){ $output = str_replace(' ', ' ', substr($configs[$param],0,8)); print "";} else { print"";} + $param="starNetInfo" . $i; + if(isset($configs[$param])){ print "";} else { print"";} + $param="starNetUserTimeout" . $i; + if(isset($configs[$param])){ print "";} else { print"";} + $param="starNetGroupTimeout" . $i; + if(isset($configs[$param])){ print "";} else { print"";} + print "\n"; + } } ?>
".str_replace(' ', ' ', substr($rptrcall,0,8))."".str_replace(' ', ' ', substr($configs[$param],0,8))." AutoNo$tot[$t]
".str_replace(' ', ' ', substr($rptrcall,0,8))."".str_replace(' ', ' ', substr($configs[$param],0,8))." AutoNo$tot[$t]$statimg".str_replace(' ', ' ', substr($linkRefl,0,8))."$protocolOutgoing$local_time
$statimg".str_replace(' ', ' ', substr($linkRefl,0,8))."$protocolOutgoing$local_time
DownNone----------
DownNone----------
".str_replace(' ', ' ', substr($rptrcall,0,8))."   $statimg".str_replace(' ', ' ', substr($linkRefl,0,8))."$protocolIncoming$local_time
".str_replace(' ', ' ', substr($rptrcall,0,8))."   $statimg".str_replace(' ', ' ', substr($linkRefl,0,8))."$protocolIncoming$local_time
".str_replace(' ', ' ', substr($rptrcall,0,8))."   $statimg
".str_replace(' ', ' ', substr($gname,0,8))."$output $configs[$param] $configs[$param] $configs[$param] 
".str_replace(' ', ' ', substr($gname,0,8))."$output $configs[$param] $configs[$param] $configs[$param] 

= 1) { + if ($active >= 1) { - echo "".$lang['active_starnet_members']."\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; + echo "".$lang['active_starnet_members']."\n"; + echo "
".$lang['time']." (".date('T').")Time of Login".$lang['group']."Starnet Callsign".$lang['callsign']."Callsign
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; - $ci = 0; - $ulist = array(); - $glist = array(); - for($i = 1;$i < 6; $i++){ - if(isset($groupsx[$i])){ - $glist = $groupsx[$i]; - foreach ($glist as $gcall => $ulist){ - foreach ($ulist as $ucall => $ulogin){ - $ci++; - if($ci > 1) { $ci = 0; } - $ulogin = date("d-M-Y H:i:s", strtotime(substr($ulogin,0,19))); - $utc_time = $ulogin; + $ci = 0; + $ulist = array(); + $glist = array(); + for($i = 1;$i < 6; $i++){ + if(isset($groupsx[$i])){ + $glist = $groupsx[$i]; + foreach ($glist as $gcall => $ulist){ + foreach ($ulist as $ucall => $ulogin){ + $ci++; + if($ci > 1) { $ci = 0; } + $ulogin = date("d-M-Y H:i:s", strtotime(substr($ulogin,0,19))); + $utc_time = $ulogin; $utc_tz = new DateTimeZone('UTC'); $local_tz = new DateTimeZone(date_default_timezone_get ()); $dt = new DateTime($utc_time, $utc_tz); $dt->setTimeZone($local_tz); $local_time = $dt->format('H:i:s M jS'); - $groupz = str_replace(' ', ' ', substr($gcall,0,8)); - $ucall = str_replace(' ', '', substr($ucall,0,8)); - print ""; - print ""; - print ""; - print ""; - print "\n"; - } - } - } - } - echo "
".$lang['time']." (".date('T').")Time of Login".$lang['group']."Starnet Callsign".$lang['callsign']."Callsign
$local_time$groupz$ucall
\n
\n"; - } + $groupz = str_replace(' ', ' ', substr($gcall,0,8)); + $ucall = str_replace(' ', '', substr($ucall,0,8)); + print ""; + print "$local_time"; + print "$groupz"; + print "$ucall"; + print "\n"; + } + } + } + } + echo "\n
\n"; + } + +?> diff --git a/dstarrepeater/css_connections.php b/dstarrepeater/css_connections.php index d87b0f1..8329b9c 100644 --- a/dstarrepeater/css_connections.php +++ b/dstarrepeater/css_connections.php @@ -1,24 +1,4 @@ -=1) { $ci = 0; if ($linkLog = fopen($linkLogPath,'r')) { - $i=0; - while ($linkLine = fgets($linkLog)) { + $i=0; + while ($linkLine = fgets($linkLog)) { // 2013-02-27 19:49:27: CCS link - Rptr: DB0LJ B Remote: DL5DI Dir: Incoming if(preg_match_all('/^(.{19}).*(C[A-Za-z]*).*Rptr: (.{8}).*Remote: (.{8}).*Dir: (.{8})$/',$linkLine,$linx) > 0){ - $utc_time = $linx[1][0]; + $utc_time = $linx[1][0]; $utc_tz = new DateTimeZone('UTC'); $local_tz = new DateTimeZone(date_default_timezone_get ()); $dt = new DateTime($utc_time, $utc_tz); $dt->setTimeZone($local_tz); $local_time = $dt->format('H:i:s M jS'); - $linkDate = $local_time; + $linkDate = $local_time; $linkType = $linx[2][0]; $linkRptr = $linx[3][0]; $linkRem = $linx[4][0]; $linkDir = $linx[5][0]; - $ci++; - if($ci > 1) { $ci = 0; } - print ""; - print "$linkRptr"; - print "$linkRem"; - print "CCS"; - print "$linkDir"; - print "$linkDate"; - print "\n"; - } - } - fclose($linkLog); + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + print "$linkRptr"; + print "$linkRem"; + print "CCS"; + print "$linkDir"; + print "$linkDate"; + print "\n"; + } + } + fclose($linkLog); } print "\n
\n"; @@ -84,12 +64,13 @@ if (exec('grep "CCS link" '.$linkLogPath.' | wc -l') >=1) { $stn_is_set = 0; for($i = 1;$i < 6; $i++){ - $param="starNetCallsign" . $i; - if(isset($configs[$param])) { - $stn_is_set = 1; - break; - } + $param="starNetCallsign" . $i; + if(isset($configs[$param])) { + $stn_is_set = 1; + break; + } } if($stn_is_set > 0){ - include_once $_SERVER['DOCUMENT_ROOT'].'/dstarrepeater/active_starnet_groups.php'; + include_once $_SERVER['DOCUMENT_ROOT'].'/dstarrepeater/active_starnet_groups.php'; } +?> diff --git a/dstarrepeater/gateway_software_config.php b/dstarrepeater/gateway_software_config.php index e906978..cb62df0 100644 --- a/dstarrepeater/gateway_software_config.php +++ b/dstarrepeater/gateway_software_config.php @@ -1,6 +1,7 @@ +
- +
ircDDB NetworkAPRS HostCCSDCSDExtraDPlusD-RatsInfoircDDBEchoLog
";} ?>
+
diff --git a/dstarrepeater/last_herd.php b/dstarrepeater/last_herd.php index e9c8332..754ce10 100644 --- a/dstarrepeater/last_herd.php +++ b/dstarrepeater/last_herd.php @@ -1,28 +1,5 @@ -/tmp/lastheard.log) 2>&1 &'); $ci = 0; if ($LastHeardLog = fopen("/tmp/lastheard.log",'r')) { - while ($linkLine = fgets($LastHeardLog)) { + while ($linkLine = fgets($LastHeardLog)) { if(preg_match_all('/^(.{19}).*My: (.*).*Your: (.*).*Rpt1: (.*).*Rpt2: (.*).*Flags: (.*)$/',$linkLine,$linx) > 0){ - $ci++; - if($ci > 1) { $ci = 0; } + $ci++; + if($ci > 1) { $ci = 0; } + print ""; $QSODate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); - - // Every value below is parsed out of /var/log/pi-star/Headers.log - // — log lines produced by RF traffic, where the - // transmitting station sets the callsign field. Without - // escaping, a hostile callsign lands in the dashboard's - // ~3 second AJAX refresh. Normalise once here so each - // echo below works on safe values. - // - // $myCallRaw — raw 8-char callsign window - // $myCallHtml — HTML-safe display form - // $myCallLink — first whitespace-delimited token (the - // callsign without the space-padded - // suffix) — used for href URLs - // $myCallLinkHtml / $myCallLinkUrl — the URL forms - // $myIdHtml — 4-char ID after the `/` (HTML-safe) - // $yourCallHtml / $rpt1Html / $rpt2Html — target + - // repeaters with ` ` substitution applied AFTER - // escaping so the literal entity isn't double-encoded. - $myCallRaw = str_replace(' ', '', substr($linx[2][0],0,8)); - $myCallHtml = htmlspecialchars($myCallRaw, ENT_QUOTES, 'UTF-8'); - $myCallLink = strtok(substr($linx[2][0],0,8), " "); - $myCallLinkUrl = rawurlencode((string)$myCallLink); - $myIdHtml = htmlspecialchars(str_replace(' ', '', substr($linx[2][0],9,4)), ENT_QUOTES, 'UTF-8'); - $yourCallHtml = str_replace(' ', ' ', - htmlspecialchars(substr($linx[3][0],0,8), ENT_QUOTES, 'UTF-8')); - $rpt1Html = str_replace(' ', ' ', - htmlspecialchars(substr($linx[4][0],0,8), ENT_QUOTES, 'UTF-8')); - $rpt2Html = str_replace(' ', ' ', - htmlspecialchars(substr($linx[5][0],0,8), ENT_QUOTES, 'UTF-8')); - - $utc_time = $QSODate; + $MyCall = str_replace(' ', '', substr($linx[2][0],0,8)); + $MyCallLink = strtok(substr($linx[2][0],0,8), " "); + $MyId = str_replace(' ', '', substr($linx[2][0],9,4)); + $YourCall = str_replace(' ', ' ', substr($linx[3][0],0,8)); + $Rpt1 = str_replace(' ', ' ', substr($linx[4][0],0,8)); + $Rpt2 = str_replace(' ', ' ', substr($linx[5][0],0,8)); + $utc_time = $QSODate; $utc_tz = new DateTimeZone('UTC'); $local_tz = new DateTimeZone(date_default_timezone_get ()); $dt = new DateTime($utc_time, $utc_tz); $dt->setTimeZone($local_tz); $local_time = $dt->format('H:i:s M jS'); - print ""; - print "$local_time"; - print "
$myCallHtml"; - if($myIdHtml !== '') { print "/$myIdHtml
"; } - else { print "
"; } - print "$yourCallHtml"; - print "$rpt1Html"; - print "$rpt2Html"; - print "\n"; - } - } - fclose($LastHeardLog); + print "$local_time"; + print "
$MyCall"; + if($MyId) { print "/".$MyId."
"; } + else { print "
(dPRS)
"; } + print "$YourCall"; + print "$Rpt1"; + print "$Rpt2"; + print "\n"; + } + } + fclose($LastHeardLog); } ?> diff --git a/dstarrepeater/link_manager.php b/dstarrepeater/link_manager.php index 7d1cc2b..00ae70f 100644 --- a/dstarrepeater/link_manager.php +++ b/dstarrepeater/link_manager.php @@ -1,101 +1,69 @@ ...HTML... ` - * template syntax — preserve the colons. - * - * Also surfaces a "PiStar-Keeper Logbook" panel below the form when - * /usr/local/sbin/pistar-keeper is running (last 5 entries from - * /var/pistar-keeper/pistar-keeper.log + a download link). - */ - - -require_once($_SERVER['DOCUMENT_ROOT'] . '/config/security_headers.php'); -setSecurityHeaders(); - if ($_SERVER["PHP_SELF"] == "/admin/index.php") { -include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code +include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code if (!empty($_POST) && isset($_POST["dstrMgrSubmit"])): //if (!empty($_POST)): if (preg_match('/[^A-Z]/',$_POST["Link"])) { unset ($_POST["Link"]);} if ($_POST["Link"] == "LINK") { - if (preg_match('/[^A-Za-z0-9 ]/',$_POST["RefName"])) { unset ($_POST["RefName"]);} - if (preg_match('/[^A-Z]/',$_POST["Letter"])) { unset ($_POST["Letter"]);} - if (preg_match('/[^A-Z0-9 ]/',$_POST["Module"])) { unset ($_POST["Module"]);} - } + if (preg_match('/[^A-Za-z0-9 ]/',$_POST["RefName"])) { unset ($_POST["RefName"]);} + if (preg_match('/[^A-Z]/',$_POST["Letter"])) { unset ($_POST["Letter"]);} + if (preg_match('/[^A-Z0-9 ]/',$_POST["Module"])) { unset ($_POST["Module"]);} + } if ($_POST["Link"] == "UNLINK") { - if (preg_match('/[^A-Z0-9 ]/',$_POST["Module"])) { unset ($_POST["Module"]);} - } - + if (preg_match('/[^A-Z0-9 ]/',$_POST["Module"])) { unset ($_POST["Module"]);} + } + if (empty($_POST["RefName"]) || empty($_POST["Letter"]) || empty($_POST["Module"])) { echo "Somthing wrong with your input, try again";} else { - if (strlen($_POST["RefName"]) != 7) { - $targetRef = str_pad($_POST["RefName"], 7, " "); - } else { - $targetRef = $_POST["RefName"]; - } - $targetRef = $targetRef.$_POST["Letter"]; - $targetRef = strtoupper($targetRef); - $module = $_POST["Module"]; + if (strlen($_POST["RefName"]) != 7) { + $targetRef = str_pad($_POST["RefName"], 7, " "); + } else { + $targetRef = $_POST["RefName"]; + } + $targetRef = $targetRef.$_POST["Letter"]; + $targetRef = strtoupper($targetRef); + $module = $_POST["Module"]; - if (strlen($module) != 8) { //Fix the length of the module information - $moduleFixedCs = strlen($module) - 1; //Length of the string, -1 + if (strlen($module) != 8) { //Fix the length of the module information + $moduleFixedCs = strlen($module) - 1; //Length of the string, -1 $moduleFixedBand = substr($module, -1); //Single Band Letter in the 8th position $moduleFixedCallPad = str_pad(substr($module, 0, $moduleFixedCs), 7); //Pad the callsign area to 7 chars $module = $moduleFixedCallPad.$moduleFixedBand; //Re add the band information }; - $unlinkCommand = "sudo remotecontrold \"".$module."\" unlink"; - $linkCommand = "sudo remotecontrold \"".$module."\" link never \"".$targetRef."\""; + $unlinkCommand = "sudo remotecontrold \"".$module."\" unlink"; + $linkCommand = "sudo remotecontrold \"".$module."\" link never \"".$targetRef."\""; - if ($module != $targetRef && $_POST["Link"] == "LINK") { // Sanity check that we are not connecting to ourself - echo "D-Star Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo htmlspecialchars((string)exec($linkCommand), ENT_QUOTES, 'UTF-8'); - echo "
\n"; - } - if ($module == $targetRef && $_POST["Link"] == "LINK") { // Sanity Check Failed - echo "D-Star Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Cannot link to myself - Aborting link request!"; - echo "
\n"; - } - if ($_POST["Link"] == "UNLINK") { // Allow Unlink no matter what - echo "D-Star Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo htmlspecialchars((string)exec($unlinkCommand), ENT_QUOTES, 'UTF-8'); - echo "
\n"; - } - } + if ($module != $targetRef && $_POST["Link"] == "LINK") { // Sanity check that we are not connecting to ourself + echo "
\nD-Star Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($linkCommand); + echo "
\n
\n"; + } + if ($module == $targetRef && $_POST["Link"] == "LINK") { // Sanity Check Failed + echo "
\nD-Star Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Cannot link to myself - Aborting link request!"; + echo "
\n
\n"; + } + if ($_POST["Link"] == "UNLINK") { // Allow Unlink no matter what + echo "
\nD-Star Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($unlinkCommand); + echo "
\n
\n"; + } + } unset($_POST); echo ''; else: ?> +
- @@ -124,10 +92,10 @@ else: ?>
Radio ModuleRadio Module @@ -208,26 +176,30 @@ fclose($dextraFile);
+
\n"; - echo "PiStar-Keeper Logbook\n"; - echo "\n"; - echo " \n"; - echo " \n"; - echo " \n"; + { + echo "
\n"; + echo "
\n"; + echo "PiStar-Keeper Logbook\n"; + echo "
PiStar-Keeper Log Entries (UTC)PiStar-Keeper Log Entries (UTC)
\n"; + echo " \n"; + echo " \n"; + echo " \n"; - exec ("tail -n 5 /var/pistar-keeper/pistar-keeper.log", $lines); - $counter = 0; - foreach ($lines as $line) { - echo "\n"; - $counter++; - } + exec ("tail -n 5 /var/pistar-keeper/pistar-keeper.log", $lines); + $counter = 0; + foreach ($lines as $line) { + echo "\n"; + $counter++; + } - echo "
PiStar-Keeper Log Entries (UTC)PiStar-Keeper Log Entries (UTC)
".$lines[$counter]."
".$lines[$counter]."
\n"; - } + echo "\n"; + echo "\n"; + } } +?> diff --git a/dstarrepeater/local_tx.php b/dstarrepeater/local_tx.php index 4e0dd06..ba26a87 100644 --- a/dstarrepeater/local_tx.php +++ b/dstarrepeater/local_tx.php @@ -1,30 +1,5 @@ -/tmp/worked.log) 2>&1 &'); $ci = 0; if ($WorkedLog = fopen("/tmp/worked.log",'r')) { - while ($linkLine = fgets($WorkedLog)) { + while ($linkLine = fgets($WorkedLog)) { if(preg_match_all('/^(.{19}).*My: (.*).*Your: (.*).*Rpt1: (.*).*Rpt2: (.*).*Flags: (.*)$/',$linkLine,$linx) > 0){ - $ci++; - if($ci > 1) { $ci = 0; } - $QSODate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); - - // Same normalisation pattern as dstarrepeater/last_herd.php — - // see the note in that file for the rationale. - $myCallRaw = str_replace(' ', '', substr($linx[2][0],0,8)); - $myCallHtml = htmlspecialchars($myCallRaw, ENT_QUOTES, 'UTF-8'); - $myCallLink = strtok(substr($linx[2][0],0,8), " "); - $myCallLinkUrl = rawurlencode((string)$myCallLink); - $myIdHtml = htmlspecialchars(str_replace(' ', '', substr($linx[2][0],9,4)), ENT_QUOTES, 'UTF-8'); - $yourCallHtml = str_replace(' ', ' ', - htmlspecialchars(substr($linx[3][0],0,8), ENT_QUOTES, 'UTF-8')); - $rpt1Html = str_replace(' ', ' ', - htmlspecialchars(substr($linx[4][0],0,8), ENT_QUOTES, 'UTF-8')); - $rpt2Html = str_replace(' ', ' ', - htmlspecialchars(substr($linx[5][0],0,8), ENT_QUOTES, 'UTF-8')); - - $utc_time = $QSODate; + $ci++; + if($ci > 1) { $ci = 0; } + print ""; + $QSODate = date("d-M-Y H:i:s", strtotime(substr($linx[1][0],0,19))); + $MyCall = str_replace(' ', '', substr($linx[2][0],0,8)); + $MyCallLink = strtok(substr($linx[2][0],0,8), " "); + $MyId = str_replace(' ', '', substr($linx[2][0],9,4)); + $YourCall = str_replace(' ', ' ', substr($linx[3][0],0,8)); + $Rpt1 = str_replace(' ', ' ', substr($linx[4][0],0,8)); + $Rpt2 = str_replace(' ', ' ', substr($linx[5][0],0,8)); + $utc_time = $QSODate; $utc_tz = new DateTimeZone('UTC'); $local_tz = new DateTimeZone(date_default_timezone_get ()); $dt = new DateTime($utc_time, $utc_tz); $dt->setTimeZone($local_tz); $local_time = $dt->format('H:i:s M jS'); - print ""; - print "$local_time"; - print "
$myCallHtml"; - if($myIdHtml !== '') { print "/$myIdHtml
(dPRS)
"; } - else { print "
(dPRS)
"; } - print "$yourCallHtml"; - print "$rpt1Html"; - print "$rpt2Html"; + print "$local_time"; + print "
$MyCall"; + if($MyId) { print "/".$MyId."
(dPRS)
"; } + else { print "
(dPRS)
"; } + print "$YourCall"; + print "$Rpt1"; + print "$Rpt2"; print "\n"; - } - } - fclose($WorkedLog); + } + } + fclose($WorkedLog); } ?> diff --git a/dstarrepeater/system.php b/dstarrepeater/system.php index e80d978..036bb10 100644 --- a/dstarrepeater/system.php +++ b/dstarrepeater/system.php @@ -1,30 +1,5 @@ - 1000) { $cpuTempC = round($cpuTempCRaw / 1000, 1); } else { $cpuTempC = round($cpuTempCRaw, 1); } $cpuTempF = round(+$cpuTempC * 9 / 5 + 32, 1); if ($cpuTempC < 50) { $cpuTempHTML = "".$cpuTempC."°C / ".$cpuTempF."°F\n"; } @@ -60,9 +35,9 @@ if ($cpuTempC >= 69) { $cpuTempHTML = "".$cpuTemp CPU Temp - = 16) { $h = substr($h, 0, 14) . '..'; } echo htmlspecialchars((string)$h, ENT_QUOTES, 'UTF-8'); ?> - - + = 16) { echo substr(php_uname('n'), 0, 14) . '..'; } else { echo php_uname('n'); } ?> + + / / diff --git a/lang/catalan_es.php b/lang/catalan_es.php index a21a7c3..2500760 100644 --- a/lang/catalan_es.php +++ b/lang/catalan_es.php @@ -6,152 +6,153 @@ // 15-Oct-2018 . Ortographical fixes by C31FR - Franc // $lang = array ( - // Banner texts - "digital_voice" => "Veu Digital", - "configuration" => "Configuració", - "dashboard_for" => "Tauler de control de", - // Banner links - "dashboard" => "Tauler de Control", - "admin" => "Administrar", - "power" => "Reiniciar/Apagar", - "update" => "Actualitzar", - "backup_restore" => "Fer/Restaurar còpia seguretat", - "factory_reset" => "Restaurar estat de fàbrica", - "live_logs" => "Informes/Logs", - // Config page section headdings - "hardware_info" => "Informació del maquinari", - "control_software" => "Control de programari", - "mmdvmhost_config" => "Configuració de MMDVMHost", - "general_config" => "Configuració General", - "dmr_config" => "Configuració de DMR", - "dstar_config" => "Configuració de DSTAR", - "ysf_config" => "Configuració de Yaesu C4FM fusion", - "p25_config" => "Configuració de P25", - "nxdn_config" => "Configuració de NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "Configuració de POCSAG", - "mobilegps_config" => "Configuració GPS mòbil", - "wifi_config" => "Configuració WIFI", - "fw_config" => "Configuració del Tallafocs", - "remote_access_pw" => "Mot clau per acccés remot", - // Config Page - Section General - "setting" => "Configuració", - "value" => "Valor", - "apply" => "Aplicar", - // Config Page - Gateway Hardware Information - "hostname" => "Nom de l'amfitrió", - "kernel" => "Nucli", - "platform" => "Plataforma", - "cpu_load" => "Càrrega CPU", - "cpu_temp" => "Temperatura CPU", - // Config Page - Control Software - "controller_software" => "Controlador programari", - "controller_mode" => "Controlador de Mode", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Mode DMR", - "d-star_mode" => "Mode D-Star", - "ysf_mode" => "Mode YSF", - "p25_mode" => "Mode P25", - "nxdn_mode" => "Mode NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Tipus de pantalla", - "mode_hangtime" => "Mode temps de suspensió", - // Config Page - General Configuration - "node_call" => "Indicatiu del Node", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Freqüència RX/TX", - "lattitude" => "Latitud", - "longitude" => "Longitud", - "town" => "Ciutat", - "country" => "País", - "url" => "URL", - "radio_type" => "Ràdio/Tipus de mòdem", - "node_type" => "Tipus de Node", - "timezone" => "Zona horària", - "dash_lang" => "Idioma del Tauler de Control", - // Config Page - DMR Configuration - "dmr_master" => "Màster DMR (MMDVMHost)", - "bm_master" => "Màster BrandMeister", - "bm_network" => "Xarxa BrandMeister", - "dmr_plus_master" => "Màster DMR+", - "dmr_plus_network" => "Xarxa DMR+", - "xlx_master" => "Màster XLX", - "xlx_enable" => "Habilitar màster XLX", - "dmr_cc" => "Codi de color DMR", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 indicatiu de crida", - "dstar_rpt2" => "RPT2 indicatiu de crida", - "dstar_irc_password" => "mot clau d'ircDDBGateway", - "dstar_default_ref" => "Reflector predeterminat", - "aprs_host" => "Servidor d'APRS", - "dstar_irc_lang" => "Idioma d'ircDDBGateway", - "dstar_irc_time" => "Interval de Balissa", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF Arrencant Host", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 Arrencant Host", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN Arrencant Host", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "Activació del GPS mòbil", - "mobilegps_port" => "Port del GPS", - "mobilegps_speed" => "Velocitat del port del GPS", - // Config Page - Firewall Configuration - "fw_dash" => "Tauler d'accés", - "fw_irc" => "ircDDBGateway Remot", - "fw_ssh" => "Accés per SSH", - // Config Page - Password - "user" => "Nom d'usuari", - "password" => "contrasenya", - "set_password" => "Establir contrasenya", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Modes habilitats", - "net_status" => "Estat de la xarxa", - "internet" => "Internet", - "radio_info" => "Informació de Ràdio", - "dstar_repeater" => "Repetidor D-Star", - "dstar_net" => "Xarxa D-Star", - "dmr_repeater" => "Repetidor DMR", - "dmr_master" => "Màster DMR", - "ysf_net" => "Xarxa YSF", - "p25_radio" => "Ràdio P25", - "p25_net" => "Xarxa P25", - "nxdn_radio" => "Ràdio NXDN", - "nxdn_net" => "Xarxa NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Hora", - "mode" => "Mode", - "callsign" => "Indicatiu", - "target" => "Destí", - "src" => "SRC", - "dur" => "DUR", - "loss" => "Pèrdua", - "ber" => "BER", - // POCSAG Specific - "pocsag_list" => "Activitat de passarel·la DAPNET", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Missatge", - // Dashboard - Extra Info - "group" => "Grup", - "logoff" => "Finalitzar", - "info" => "Informació", - "utot" => "UTOT", - "gtot" => "GTOT", - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Últimes 20 trucades rebudes", - "local_tx_list" => "Últimes 20 trucades rebudes via ràdio", - "active_starnet_groups" => "Grups actius Starnet", - "active_starnet_members" => "Membres actius grup Starnet", - "d-star_link_manager" => "Gestor d'enllaços D-Star", - "d-star_link_status" => "Informació d'enllaços D-Star", - "service_status" => "Estat del servei" + // Banner texts + "digital_voice" => "Veu Digital", + "configuration" => "Configuració", + "dashboard_for" => "Tauler de control de", + // Banner links + "dashboard" => "Tauler de Control", + "admin" => "Administrar", + "power" => "Reiniciar/Apagar", + "update" => "Actualitzar", + "backup_restore" => "Fer/Restaurar còpia seguretat", + "factory_reset" => "Restaurar estat de fàbrica", + "live_logs" => "Informes/Logs", + // Config page section headdings + "hardware_info" => "Informació del maquinari", + "control_software" => "Control de programari", + "mmdvmhost_config" => "Configuració de MMDVMHost", + "general_config" => "Configuració General", + "dmr_config" => "Configuració de DMR", + "dstar_config" => "Configuració de DSTAR", + "ysf_config" => "Configuració de Yaesu C4FM fusion", + "p25_config" => "Configuració de P25", + "nxdn_config" => "Configuració de NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuració de POCSAG", + "mobilegps_config" => "Configuració GPS mòbil", + "wifi_config" => "Configuració WIFI", + "fw_config" => "Configuració del Tallafocs", + "remote_access_pw" => "Mot clau per acccés remot", + // Config Page - Section General + "setting" => "Configuració", + "value" => "Valor", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Nom de l'amfitrió", + "kernel" => "Nucli", + "platform" => "Plataforma", + "cpu_load" => "Càrrega CPU", + "cpu_temp" => "Temperatura CPU", + // Config Page - Control Software + "controller_software" => "Controlador programari", + "controller_mode" => "Controlador de Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Mode DMR", + "d-star_mode" => "Mode D-Star", + "ysf_mode" => "Mode YSF", + "p25_mode" => "Mode P25", + "nxdn_mode" => "Mode NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Tipus de pantalla", + "mode_hangtime" => "Mode temps de suspensió", + // Config Page - General Configuration + "node_call" => "Indicatiu del Node", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Freqüència RX/TX", + "lattitude" => "Latitud", + "longitude" => "Longitud", + "town" => "Ciutat", + "country" => "País", + "url" => "URL", + "radio_type" => "Ràdio/Tipus de mòdem", + "node_type" => "Tipus de Node", + "timezone" => "Zona horària", + "dash_lang" => "Idioma del Tauler de Control", + // Config Page - DMR Configuration + "dmr_master" => "Màster DMR (MMDVMHost)", + "bm_master" => "Màster BrandMeister", + "bm_network" => "Xarxa BrandMeister", + "dmr_plus_master" => "Màster DMR+", + "dmr_plus_network" => "Xarxa DMR+", + "xlx_master" => "Màster XLX", + "xlx_enable" => "Habilitar màster XLX", + "dmr_cc" => "Codi de color DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 indicatiu de crida", + "dstar_rpt2" => "RPT2 indicatiu de crida", + "dstar_irc_password" => "mot clau d'ircDDBGateway", + "dstar_default_ref" => "Reflector predeterminat", + "aprs_host" => "Servidor d'APRS", + "dstar_irc_lang" => "Idioma d'ircDDBGateway", + "dstar_irc_time" => "Interval de Balissa", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Arrencant Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Arrencant Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Arrencant Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "Activació del GPS mòbil", + "mobilegps_port" => "Port del GPS", + "mobilegps_speed" => "Velocitat del port del GPS", + // Config Page - Firewall Configuration + "fw_dash" => "Tauler d'accés", + "fw_irc" => "ircDDBGateway Remot", + "fw_ssh" => "Accés per SSH", + // Config Page - Password + "user" => "Nom d'usuari", + "password" => "contrasenya", + "set_password" => "Establir contrasenya", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes habilitats", + "net_status" => "Estat de la xarxa", + "internet" => "Internet", + "radio_info" => "Informació de Ràdio", + "dstar_repeater" => "Repetidor D-Star", + "dstar_net" => "Xarxa D-Star", + "dmr_repeater" => "Repetidor DMR", + "dmr_master" => "Màster DMR", + "ysf_net" => "Xarxa YSF", + "p25_radio" => "Ràdio P25", + "p25_net" => "Xarxa P25", + "nxdn_radio" => "Ràdio NXDN", + "nxdn_net" => "Xarxa NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Hora", + "mode" => "Mode", + "callsign" => "Indicatiu", + "target" => "Destí", + "src" => "SRC", + "dur" => "DUR", + "loss" => "Pèrdua", + "ber" => "BER", + // POCSAG Specific + "pocsag_list" => "Activitat de passarel·la DAPNET", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Missatge", + // Dashboard - Extra Info + "group" => "Grup", + "logoff" => "Finalitzar", + "info" => "Informació", + "utot" => "UTOT", + "gtot" => "GTOT", + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Últimes 20 trucades rebudes", + "local_tx_list" => "Últimes 20 trucades rebudes via ràdio", + "active_starnet_groups" => "Grups actius Starnet", + "active_starnet_members" => "Membres actius grup Starnet", + "d-star_link_manager" => "Gestor d'enllaços D-Star", + "d-star_link_status" => "Informació d'enllaços D-Star", + "service_status" => "Estat del servei" ); +?> diff --git a/lang/chinese_cn.php b/lang/chinese_cn.php index b445b04..0cfd820 100644 --- a/lang/chinese_cn.php +++ b/lang/chinese_cn.php @@ -2,155 +2,156 @@ // Chinese CN (simplified Chinese characters) Language Pack // Translated by Le Peng(BD7KLE), Email: bd7kle@gmail.com // Yuan Wang(BG3MDO), Email: bg3mdo@gmail.com -// Maintained by Yuan Wang(BG3MDO), Email: bg3mdo@gmail.com +// Maintained by Yuan Wang(BG3MDO), Email: bg3mdo@gmail.com // Last update on 03/08/2017 $lang = array ( - // Banner texts - "digital_voice" => "数字语音", - "configuration" => "配置", - "dashboard_for" => "仪表盘 -", - // Banner links - "dashboard" => "仪表盘", - "admin" => "管理", - "power" => "电源", - "update" => "更新", - "backup_restore" => "备份/恢复", - "factory_reset" => "恢复出厂设置", - "live_logs" => "日志", - // Config page section headdings - "hardware_info" => "网关硬件信息", - "control_software" => "控制软件", - "mmdvmhost_config" => "MMDVMHost 配置", - "general_config" => "常规配置", - "dmr_config" => "DMR 配置", - "dstar_config" => "D-Star 配置", - "ysf_config" => "Yaesu System Fusion 配置", - "p25_config" => "P25 配置", - "nxdn_config" => "NXDN 配置", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG 配置", - "mobilegps_config" => "Mobile GPS Configuration", - "fw_config" => "防火墙配置", - "remote_access_pw" => "远程访问密码", - // Config Page - Section General - "setting" => "设置", - "value" => "设置值", - "apply" => "应用设置", - // Config Page - Gateway Hardware Information - "hostname" => "主机名", - "kernel" => "内核", - "platform" => "平台", - "cpu_load" => "CPU 负荷", - "cpu_temp" => "CPU 温度", - // Config Page - Control Software - "controller_software" => "控制器软件", - "controller_mode" => "控制器模式", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR 模式", - "d-star_mode" => "D-Star 模式", - "ysf_mode" => "YSF 模式", - "p25_mode" => "P25 模式", - "nxdn_mode" => "NXDN 模式", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM 显示屏类型", - "mode_hangtime" => "模式停留时间", - // Config Page - General Configuration - "node_call" => "节点呼号", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "电台频率", - "lattitude" => "纬度", - "longitude" => "经度", - "town" => "城市", - "country" => "国家", - "url" => "URL", - "radio_type" => "电台/调制解调器类型", - "node_type" => "节点类型", - "timezone" => "时区", - "dash_lang" => "仪表盘语言", - // Config Page - DMR Configuration - "dmr_master" => "DMR 主机 (MMDVMHost)", - "bm_master" => "BrandMeister 主机 ", - "bm_network" => "BrandMeister 网络", - "dmr_plus_master" => "DMR+ 主机 ", - "dmr_plus_network" => "DMR+ 网络", - "xlx_master" => "XLX 主机 ", - "xlx_enable" => "XLX 主机启用", - "dmr_cc" => "DMR 彩色码", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 呼号", - "dstar_rpt2" => "RPT2 呼号", - "dstar_irc_password" => "ircDDBGateway 密码", - "dstar_default_ref" => "默认反射器", - "aprs_host" => "APRS 服务器", - "dstar_irc_lang" => "ircDDBGateway 语言", - "dstar_irc_time" => "时间通告", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF 默认服务器", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 默认服务器", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN 默认服务器", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "仪表盘访问", - "fw_irc" => "ircDDBGateway 远程", - "fw_ssh" => "SSH访问", - // Config Page - Password - "user" => "用户名", - "password" => "密码", - "set_password" => "设置密码", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "启动的模式", - "net_status" => "网络状态", - "internet" => "互联网", - "radio_info" => "电台信息", - "dstar_repeater" => "D-Star 中继", - "dstar_net" => "D-Star 网络", - "dmr_repeater" => "DMR 中继", - "dmr_master" => "DMR 主机", - "ysf_net" => "YSF 网络", - "p25_radio" => "P25 电台", - "p25_net" => "P25 网络", - "nxdn_radio" => "NXDN 电台", - "nxdn_net" => "NXDN 网络", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "时间", - "mode" => "模式", - "callsign" => "呼号", - "target" => "目标", - "src" => "源", // Short version of "Source" - "dur" => "时长", // Short version of "Duration" - "loss" => "丢失", - "ber" => "误码率", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "组", - "logoff" => "注销", - "info" => "信息", - "utot" => "用户超时", // Short for User Timeout - "gtot" => "组超时", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "网关上最后 20 个呼叫", - "local_tx_list" => "最后 20 个本地呼叫", - "active_starnet_groups" => "激活的 Starnet 组", - "active_starnet_members" => "激活的 Starnet 组成员", - "d-star_link_manager" => "D-Star 连接管理器", - "d-star_link_status" => "D-Star 连接信息", - "service_status" => "服务状态" + // Banner texts + "digital_voice" => "数字语音", + "configuration" => "配置", + "dashboard_for" => "仪表盘 -", + // Banner links + "dashboard" => "仪表盘", + "admin" => "管理", + "power" => "电源", + "update" => "更新", + "backup_restore" => "备份/恢复", + "factory_reset" => "恢复出厂设置", + "live_logs" => "日志", + // Config page section headdings + "hardware_info" => "网关硬件信息", + "control_software" => "控制软件", + "mmdvmhost_config" => "MMDVMHost 配置", + "general_config" => "常规配置", + "dmr_config" => "DMR 配置", + "dstar_config" => "D-Star 配置", + "ysf_config" => "Yaesu System Fusion 配置", + "p25_config" => "P25 配置", + "nxdn_config" => "NXDN 配置", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG 配置", + "mobilegps_config" => "Mobile GPS Configuration", + "fw_config" => "防火墙配置", + "remote_access_pw" => "远程访问密码", + // Config Page - Section General + "setting" => "设置", + "value" => "设置值", + "apply" => "应用设置", + // Config Page - Gateway Hardware Information + "hostname" => "主机名", + "kernel" => "内核", + "platform" => "平台", + "cpu_load" => "CPU 负荷", + "cpu_temp" => "CPU 温度", + // Config Page - Control Software + "controller_software" => "控制器软件", + "controller_mode" => "控制器模式", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR 模式", + "d-star_mode" => "D-Star 模式", + "ysf_mode" => "YSF 模式", + "p25_mode" => "P25 模式", + "nxdn_mode" => "NXDN 模式", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM 显示屏类型", + "mode_hangtime" => "模式停留时间", + // Config Page - General Configuration + "node_call" => "节点呼号", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "电台频率", + "lattitude" => "纬度", + "longitude" => "经度", + "town" => "城市", + "country" => "国家", + "url" => "URL", + "radio_type" => "电台/调制解调器类型", + "node_type" => "节点类型", + "timezone" => "时区", + "dash_lang" => "仪表盘语言", + // Config Page - DMR Configuration + "dmr_master" => "DMR 主机 (MMDVMHost)", + "bm_master" => "BrandMeister 主机 ", + "bm_network" => "BrandMeister 网络", + "dmr_plus_master" => "DMR+ 主机 ", + "dmr_plus_network" => "DMR+ 网络", + "xlx_master" => "XLX 主机 ", + "xlx_enable" => "XLX 主机启用", + "dmr_cc" => "DMR 彩色码", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 呼号", + "dstar_rpt2" => "RPT2 呼号", + "dstar_irc_password" => "ircDDBGateway 密码", + "dstar_default_ref" => "默认反射器", + "aprs_host" => "APRS 服务器", + "dstar_irc_lang" => "ircDDBGateway 语言", + "dstar_irc_time" => "时间通告", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF 默认服务器", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 默认服务器", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN 默认服务器", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "仪表盘访问", + "fw_irc" => "ircDDBGateway 远程", + "fw_ssh" => "SSH访问", + // Config Page - Password + "user" => "用户名", + "password" => "密码", + "set_password" => "设置密码", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "启动的模式", + "net_status" => "网络状态", + "internet" => "互联网", + "radio_info" => "电台信息", + "dstar_repeater" => "D-Star 中继", + "dstar_net" => "D-Star 网络", + "dmr_repeater" => "DMR 中继", + "dmr_master" => "DMR 主机", + "ysf_net" => "YSF 网络", + "p25_radio" => "P25 电台", + "p25_net" => "P25 网络", + "nxdn_radio" => "NXDN 电台", + "nxdn_net" => "NXDN 网络", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "时间", + "mode" => "模式", + "callsign" => "呼号", + "target" => "目标", + "src" => "源", // Short version of "Source" + "dur" => "时长", // Short version of "Duration" + "loss" => "丢失", + "ber" => "误码率", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "组", + "logoff" => "注销", + "info" => "信息", + "utot" => "用户超时", // Short for User Timeout + "gtot" => "组超时", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "网关上最后 20 个呼叫", + "local_tx_list" => "最后 20 个本地呼叫", + "active_starnet_groups" => "激活的 Starnet 组", + "active_starnet_members" => "激活的 Starnet 组成员", + "d-star_link_manager" => "D-Star 连接管理器", + "d-star_link_status" => "D-Star 连接信息", + "service_status" => "服务状态" ); +?> diff --git a/lang/chinese_hk.php b/lang/chinese_hk.php index 3fed26c..6e05669 100644 --- a/lang/chinese_hk.php +++ b/lang/chinese_hk.php @@ -2,155 +2,156 @@ // Chinese HK (Traditional Chinese characters) Language Pack // Translated by Le Peng(BD7KLE), Email: bd7kle@gmail.com // Yuan Wang(BG3MDO), Email: bg3mdo@gmail.com -// Maintained by Yuan Wang(BG3MDO), Email: bg3mdo@gmail.com +// Maintained by Yuan Wang(BG3MDO), Email: bg3mdo@gmail.com // Last update on 03/08/2017 $lang = array ( - // Banner texts - "digital_voice" => "數字語音", - "configuration" => "設定", - "dashboard_for" => "儀錶盤 -", - // Banner links - "dashboard" => "儀錶盤", - "admin" => "管理", - "power" => "電源", - "update" => "更新", - "backup_restore" => "備份/恢復", - "factory_reset" => "恢復出廠設定", - "live_logs" => "日誌", - // Config page section headdings - "hardware_info" => "網關硬體信息", - "control_software" => "控制軟體", - "mmdvmhost_config" => "MMDVMHost 設定", - "general_config" => "常規設定", - "dmr_config" => "DMR 設定", - "dstar_config" => "D-Star 設定", - "ysf_config" => "Yaesu System Fusion 設定", - "p25_config" => "P25 設定", - "nxdn_config" => "NXDN 設定", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG 設定", - "mobilegps_config" => "Mobile GPS Configuration", - "fw_config" => "防火墻設定", - "remote_access_pw" => "遠程訪問密碼", - // Config Page - Section General - "setting" => "設定", - "value" => "設定值", - "apply" => "應用設定", - // Config Page - Gateway Hardware Information - "hostname" => "主機名", - "kernel" => "內核", - "platform" => "平臺", - "cpu_load" => "CPU 負荷", - "cpu_temp" => "CPU 溫度", - // Config Page - Control Software - "controller_software" => "控制器軟體", - "controller_mode" => "控制器模式", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR 模式", - "d-star_mode" => "D-Star 模式", - "ysf_mode" => "YSF 模式", - "p25_mode" => "P25 模式", - "nxdn_mode" => "NXDN 模式", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM 顯示器類型", - "mode_hangtime" => "模式停留時間", - // Config Page - General Configuration - "node_call" => "節點呼號", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "電臺頻率", - "lattitude" => "緯度", - "longitude" => "經度", - "town" => "區域", - "country" => "國家", - "url" => "URL", - "radio_type" => "電臺/調製解調器類型", - "node_type" => "節點類型", - "timezone" => "時區", - "dash_lang" => "儀錶盤語言", - // Config Page - DMR Configuration - "dmr_master" => "DMR 主機 (MMDVMHost)", - "bm_master" => "BrandMeister 主機 ", - "bm_network" => "BrandMeister 網絡", - "dmr_plus_master" => "DMR+ 主機 ", - "dmr_plus_network" => "DMR+ 網絡", - "xlx_master" => "XLX 主機 ", - "xlx_enable" => "XLX 主機啟用", - "dmr_cc" => "DMR 彩色碼", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 呼號", - "dstar_rpt2" => "RPT2 呼號", - "dstar_irc_password" => "ircDDBGateway 密碼", - "dstar_default_ref" => "默認反射器", - "aprs_host" => "APRS 服務器", - "dstar_irc_lang" => "ircDDBGateway 語言", - "dstar_irc_time" => "時間通告", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF 默認服務器", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 默認服務器", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN 默認服務器", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "儀表盤訪問", - "fw_irc" => "ircDDBGateway 遠程", - "fw_ssh" => "SSH訪問", - // Config Page - Password - "user" => "用戶名", - "password" => "密碼", - "set_password" => "密碼設定", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "啟用的模式", - "net_status" => "網絡狀態", - "internet" => "互聯網", - "radio_info" => "電臺信息", - "dstar_repeater" => "D-Star 中繼", - "dstar_net" => "D-Star 網絡", - "dmr_repeater" => "DMR 中繼", - "dmr_master" => "DMR 主機", - "ysf_net" => "YSF 網絡", - "p25_radio" => "P25 電臺", - "p25_net" => "P25 網絡", - "nxdn_radio" => "NXDN 電臺", - "nxdn_net" => "NXDN 網絡", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "時間", - "mode" => "模式", - "callsign" => "呼號", - "target" => "目標", - "src" => "源", // Short version of "Source" - "dur" => "時長", // Short version of "Duration" - "loss" => "丟失", - "ber" => "誤碼率", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "組", - "logoff" => "註銷", - "info" => "信息", - "utot" => "用户超時", // Short for User Timeout - "gtot" => "組超時", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "網關上最後 20 個呼叫", - "local_tx_list" => "最後 20 個本地呼叫", - "active_starnet_groups" => "激活 Starnet 組", - "active_starnet_members" => "激活 Starnet 組成員", - "d-star_link_manager" => "D-Star 連接管理器", - "d-star_link_status" => "D-Star 連接信息", - "service_status" => "服務狀態" + // Banner texts + "digital_voice" => "數字語音", + "configuration" => "設定", + "dashboard_for" => "儀錶盤 -", + // Banner links + "dashboard" => "儀錶盤", + "admin" => "管理", + "power" => "電源", + "update" => "更新", + "backup_restore" => "備份/恢復", + "factory_reset" => "恢復出廠設定", + "live_logs" => "日誌", + // Config page section headdings + "hardware_info" => "網關硬體信息", + "control_software" => "控制軟體", + "mmdvmhost_config" => "MMDVMHost 設定", + "general_config" => "常規設定", + "dmr_config" => "DMR 設定", + "dstar_config" => "D-Star 設定", + "ysf_config" => "Yaesu System Fusion 設定", + "p25_config" => "P25 設定", + "nxdn_config" => "NXDN 設定", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG 設定", + "mobilegps_config" => "Mobile GPS Configuration", + "fw_config" => "防火墻設定", + "remote_access_pw" => "遠程訪問密碼", + // Config Page - Section General + "setting" => "設定", + "value" => "設定值", + "apply" => "應用設定", + // Config Page - Gateway Hardware Information + "hostname" => "主機名", + "kernel" => "內核", + "platform" => "平臺", + "cpu_load" => "CPU 負荷", + "cpu_temp" => "CPU 溫度", + // Config Page - Control Software + "controller_software" => "控制器軟體", + "controller_mode" => "控制器模式", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR 模式", + "d-star_mode" => "D-Star 模式", + "ysf_mode" => "YSF 模式", + "p25_mode" => "P25 模式", + "nxdn_mode" => "NXDN 模式", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM 顯示器類型", + "mode_hangtime" => "模式停留時間", + // Config Page - General Configuration + "node_call" => "節點呼號", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "電臺頻率", + "lattitude" => "緯度", + "longitude" => "經度", + "town" => "區域", + "country" => "國家", + "url" => "URL", + "radio_type" => "電臺/調製解調器類型", + "node_type" => "節點類型", + "timezone" => "時區", + "dash_lang" => "儀錶盤語言", + // Config Page - DMR Configuration + "dmr_master" => "DMR 主機 (MMDVMHost)", + "bm_master" => "BrandMeister 主機 ", + "bm_network" => "BrandMeister 網絡", + "dmr_plus_master" => "DMR+ 主機 ", + "dmr_plus_network" => "DMR+ 網絡", + "xlx_master" => "XLX 主機 ", + "xlx_enable" => "XLX 主機啟用", + "dmr_cc" => "DMR 彩色碼", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 呼號", + "dstar_rpt2" => "RPT2 呼號", + "dstar_irc_password" => "ircDDBGateway 密碼", + "dstar_default_ref" => "默認反射器", + "aprs_host" => "APRS 服務器", + "dstar_irc_lang" => "ircDDBGateway 語言", + "dstar_irc_time" => "時間通告", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF 默認服務器", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 默認服務器", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN 默認服務器", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "儀表盤訪問", + "fw_irc" => "ircDDBGateway 遠程", + "fw_ssh" => "SSH訪問", + // Config Page - Password + "user" => "用戶名", + "password" => "密碼", + "set_password" => "密碼設定", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "啟用的模式", + "net_status" => "網絡狀態", + "internet" => "互聯網", + "radio_info" => "電臺信息", + "dstar_repeater" => "D-Star 中繼", + "dstar_net" => "D-Star 網絡", + "dmr_repeater" => "DMR 中繼", + "dmr_master" => "DMR 主機", + "ysf_net" => "YSF 網絡", + "p25_radio" => "P25 電臺", + "p25_net" => "P25 網絡", + "nxdn_radio" => "NXDN 電臺", + "nxdn_net" => "NXDN 網絡", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "時間", + "mode" => "模式", + "callsign" => "呼號", + "target" => "目標", + "src" => "源", // Short version of "Source" + "dur" => "時長", // Short version of "Duration" + "loss" => "丟失", + "ber" => "誤碼率", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "組", + "logoff" => "註銷", + "info" => "信息", + "utot" => "用户超時", // Short for User Timeout + "gtot" => "組超時", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "網關上最後 20 個呼叫", + "local_tx_list" => "最後 20 個本地呼叫", + "active_starnet_groups" => "激活 Starnet 組", + "active_starnet_members" => "激活 Starnet 組成員", + "d-star_link_manager" => "D-Star 連接管理器", + "d-star_link_status" => "D-Star 連接信息", + "service_status" => "服務狀態" ); +?> diff --git a/lang/chinese_tw.php b/lang/chinese_tw.php index 0c96f43..e7a6895 100644 --- a/lang/chinese_tw.php +++ b/lang/chinese_tw.php @@ -4,151 +4,152 @@ // Last update on 02/13/2018 $lang = array ( - // Banner texts - "digital_voice" => "數位語音", - "configuration" => "組態設定", - "dashboard_for" => "控制台 -", - // Banner links - "dashboard" => "控制台", - "admin" => "管理", - "power" => "電源", - "update" => "更新", - "backup_restore" => "備份/還原", - "factory_reset" => "恢復出廠設定", - "live_logs" => "日誌", - // Config page section headdings - "hardware_info" => "硬體資訊", - "control_software" => "控制軟體", - "mmdvmhost_config" => "MMDVMHost 設定", - "general_config" => "一般設定", - "dmr_config" => "DMR 設定", - "dstar_config" => "D-Star 設定", - "ysf_config" => "Yaesu System Fusion 設定", - "p25_config" => "P25 設定", - "nxdn_config" => "NXDN 設定", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG 設定", - "mobilegps_config" => "Mobile GPS Configuration", - "fw_config" => "防火牆設定", - "remote_access_pw" => "遠端遙控密碼", - // Config Page - Section General - "setting" => "設定", - "value" => "設定值", - "apply" => "變更設定", - // Config Page - Gateway Hardware Information - "hostname" => "主機名稱", - "kernel" => "核心", - "platform" => "平台", - "cpu_load" => "CPU 負載", - "cpu_temp" => "CPU 溫度", - // Config Page - Control Software - "controller_software" => "控制器軟體", - "controller_mode" => "控制器模式", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR 模式", - "d-star_mode" => "D-Star 模式", - "ysf_mode" => "YSF 模式", - "p25_mode" => "P25 模式", - "nxdn_mode" => "NXDN 模式", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM 螢幕類型", - "mode_hangtime" => "模式保持時間", - // Config Page - General Configuration - "node_call" => "節點呼號", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "電台頻率", - "lattitude" => "緯度", - "longitude" => "經度", - "town" => "城市", - "country" => "國家", - "url" => "URL", - "radio_type" => "Modem 類型", - "node_type" => "節點類型", - "timezone" => "時區", - "dash_lang" => "介面語言", - // Config Page - DMR Configuration - "dmr_master" => "DMR 伺服器 (MMDVMHost)", - "bm_master" => "BrandMeister 伺服器", - "bm_network" => "BrandMeister 網路", - "dmr_plus_master" => "DMR+ 伺服器", - "dmr_plus_network" => "DMR+ 網路", - "xlx_master" => "XLX 伺服器", - "xlx_enable" => "啟用 XLX 伺服器", - "dmr_cc" => "DMR 色碼", - "dmr_embeddedlconly" => "僅允許指定 ID 連接", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 呼號", - "dstar_rpt2" => "RPT2 呼號", - "dstar_irc_password" => "ircDDBGateway 密碼", - "dstar_default_ref" => "預設反射器", - "aprs_host" => "APRS 伺服器", - "dstar_irc_lang" => "ircDDBGateway 語言", - "dstar_irc_time" => "時間提示", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF 預設伺服器", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 預設伺服器", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN 預設伺服器", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "控制台存取", - "fw_irc" => "ircDDBGateway 遠端遙控", - "fw_ssh" => "SSH 存取", - // Config Page - Password - "user" => "用戶名", - "password" => "密碼", - "set_password" => "密碼設定", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "已啟用模式", - "net_status" => "網路狀態", - "internet" => "網際網路", - "radio_info" => "RF 電台資訊", - "dstar_repeater" => "D-Star 中繼", - "dstar_net" => "D-Star 網路", - "dmr_repeater" => "DMR 中繼", - "dmr_master" => "DMR 伺服器", - "ysf_net" => "YSF 網路", - "p25_radio" => "P25 電台", - "p25_net" => "P25 網路", - "nxdn_radio" => "NXDN 電台", - "nxdn_net" => "NXDN 網路", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "時間", - "mode" => "模式", - "callsign" => "呼號", - "target" => "目標", - "src" => "來源", // Short version of "Source" - "dur" => "歷時", // Short version of "Duration" - "loss" => "丟失率", - "ber" => "誤碼率", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "群組", - "logoff" => "登出", - "info" => "資訊", - "utot" => "用户逾時", // Short for User Timeout - "gtot" => "群組逾時", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "最近 20 個通訊", - "local_tx_list" => "最近 20 個本地 RF 通訊", - "active_starnet_groups" => "啟用 Starnet 群組", - "active_starnet_members" => "啟用 Starnet 成員", - "d-star_link_manager" => "D-Star 連線管理", - "d-star_link_status" => "D-Star 連線狀態", - "service_status" => "服務狀態" + // Banner texts + "digital_voice" => "數位語音", + "configuration" => "組態設定", + "dashboard_for" => "控制台 -", + // Banner links + "dashboard" => "控制台", + "admin" => "管理", + "power" => "電源", + "update" => "更新", + "backup_restore" => "備份/還原", + "factory_reset" => "恢復出廠設定", + "live_logs" => "日誌", + // Config page section headdings + "hardware_info" => "硬體資訊", + "control_software" => "控制軟體", + "mmdvmhost_config" => "MMDVMHost 設定", + "general_config" => "一般設定", + "dmr_config" => "DMR 設定", + "dstar_config" => "D-Star 設定", + "ysf_config" => "Yaesu System Fusion 設定", + "p25_config" => "P25 設定", + "nxdn_config" => "NXDN 設定", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG 設定", + "mobilegps_config" => "Mobile GPS Configuration", + "fw_config" => "防火牆設定", + "remote_access_pw" => "遠端遙控密碼", + // Config Page - Section General + "setting" => "設定", + "value" => "設定值", + "apply" => "變更設定", + // Config Page - Gateway Hardware Information + "hostname" => "主機名稱", + "kernel" => "核心", + "platform" => "平台", + "cpu_load" => "CPU 負載", + "cpu_temp" => "CPU 溫度", + // Config Page - Control Software + "controller_software" => "控制器軟體", + "controller_mode" => "控制器模式", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR 模式", + "d-star_mode" => "D-Star 模式", + "ysf_mode" => "YSF 模式", + "p25_mode" => "P25 模式", + "nxdn_mode" => "NXDN 模式", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM 螢幕類型", + "mode_hangtime" => "模式保持時間", + // Config Page - General Configuration + "node_call" => "節點呼號", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "電台頻率", + "lattitude" => "緯度", + "longitude" => "經度", + "town" => "城市", + "country" => "國家", + "url" => "URL", + "radio_type" => "Modem 類型", + "node_type" => "節點類型", + "timezone" => "時區", + "dash_lang" => "介面語言", + // Config Page - DMR Configuration + "dmr_master" => "DMR 伺服器 (MMDVMHost)", + "bm_master" => "BrandMeister 伺服器", + "bm_network" => "BrandMeister 網路", + "dmr_plus_master" => "DMR+ 伺服器", + "dmr_plus_network" => "DMR+ 網路", + "xlx_master" => "XLX 伺服器", + "xlx_enable" => "啟用 XLX 伺服器", + "dmr_cc" => "DMR 色碼", + "dmr_embeddedlconly" => "僅允許指定 ID 連接", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 呼號", + "dstar_rpt2" => "RPT2 呼號", + "dstar_irc_password" => "ircDDBGateway 密碼", + "dstar_default_ref" => "預設反射器", + "aprs_host" => "APRS 伺服器", + "dstar_irc_lang" => "ircDDBGateway 語言", + "dstar_irc_time" => "時間提示", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF 預設伺服器", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 預設伺服器", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN 預設伺服器", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "控制台存取", + "fw_irc" => "ircDDBGateway 遠端遙控", + "fw_ssh" => "SSH 存取", + // Config Page - Password + "user" => "用戶名", + "password" => "密碼", + "set_password" => "密碼設定", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "已啟用模式", + "net_status" => "網路狀態", + "internet" => "網際網路", + "radio_info" => "RF 電台資訊", + "dstar_repeater" => "D-Star 中繼", + "dstar_net" => "D-Star 網路", + "dmr_repeater" => "DMR 中繼", + "dmr_master" => "DMR 伺服器", + "ysf_net" => "YSF 網路", + "p25_radio" => "P25 電台", + "p25_net" => "P25 網路", + "nxdn_radio" => "NXDN 電台", + "nxdn_net" => "NXDN 網路", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "時間", + "mode" => "模式", + "callsign" => "呼號", + "target" => "目標", + "src" => "來源", // Short version of "Source" + "dur" => "歷時", // Short version of "Duration" + "loss" => "丟失率", + "ber" => "誤碼率", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "群組", + "logoff" => "登出", + "info" => "資訊", + "utot" => "用户逾時", // Short for User Timeout + "gtot" => "群組逾時", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "最近 20 個通訊", + "local_tx_list" => "最近 20 個本地 RF 通訊", + "active_starnet_groups" => "啟用 Starnet 群組", + "active_starnet_members" => "啟用 Starnet 成員", + "d-star_link_manager" => "D-Star 連線管理", + "d-star_link_status" => "D-Star 連線狀態", + "service_status" => "服務狀態" ); +?> diff --git a/lang/dutch_nl.php b/lang/dutch_nl.php index 4e56eb5..ed17370 100644 --- a/lang/dutch_nl.php +++ b/lang/dutch_nl.php @@ -4,152 +4,153 @@ // Updated: 04-Aug-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voice", - "configuration" => "Configuratie", - "dashboard_for" => "Dashboard voor", - // Banner links - "dashboard" => "Dashboard", - "admin" => "Admin", - "power" => "Power", - "update" => "Update", - "backup_restore" => "Backup/Restore", - "factory_reset" => "Reset all", - "live_logs" => "Actuele Logs", - // Config page section headdings - "hardware_info" => "Gateway hardware informatie", - "control_software" => "Controller Host software", - "mmdvmhost_config" => "MMDVMHost configuratie", - "general_config" => "Algemene configuratie", - "dmr_config" => "DMR configuratie", - "dstar_config" => "D-Star configuratie", - "ysf_config" => "Yaesu System Fusion configuratie", - "p25_config" => "P25 configuratie", - "nxdn_config" => "NXDN configuratie", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG configuratie", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Wireless configuratie", - "fw_config" => "Firewall configuratie", - "remote_access_pw" => "Remote Access paswoord", - // Config Page - Section General - "setting" => "Instelling", - "value" => "Waarde", - "apply" => "Toepassen", - // Config Page - Gateway Hardware Information - "hostname" => "Hostnaam", - "kernel" => "Kernel", - "platform" => "Platform", - "cpu_load" => "CPU Load", - "cpu_temp" => "CPU Temp", - // Config Page - Control Software - "controller_software" => "Controller software", - "controller_mode" => "Controller modus", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR modus", - "d-star_mode" => "D-Star modus", - "ysf_mode" => "YSF modus", - "p25_mode" => "P25 modus", - "nxdn_mode" => "NXDN modus", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM display type", - "mode_hangtime" => "Mode hangtijd", - // Config Page - General Configuration - "node_call" => "Node roepletters", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Radio frequentie", - "lattitude" => "Breedtegraad", - "longitude" => "Lengtegraad", - "town" => "Plaats", - "country" => "Land", - "url" => "URL", - "radio_type" => "Radio/Modem type", - "node_type" => "Node type", - "timezone" => "Systeem tijdzone", - "dash_lang" => "Dashboard taal", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister netwerk", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ netwerk", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master AAN", - "dmr_cc" => "DMR kleur code (CC)", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 roepletters", - "dstar_rpt2" => "RPT2 roepletters", - "dstar_irc_password" => "ircDDBGateway paswoord", - "dstar_default_ref" => "Standaard reflector", - "aprs_host" => "APRS Host", - "dstar_irc_lang" => "ircDDBGateway taal", - "dstar_irc_time" => "Tijd uitzenden", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF standaard Host", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 standaard Host", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN standaard Host", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Dashboard toegang", - "fw_irc" => "ircDDBGateway op afstand", - "fw_ssh" => "SSH toegang", - // Config Page - Password - "user" => "Gebruikersnaam", - "password" => "Paswoord", - "set_password" => "Voer paswoord in", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Actieve modi", - "net_status" => "Netwerk status", - "internet" => "Internet", - "radio_info" => "Radio info", - "dstar_repeater" => "D-Star repeater", - "dstar_net" => "D-Star netwerk", - "dmr_repeater" => "DMR repeater", - "dmr_master" => "DMR Master", - "ysf_net" => "YSF netwerk", - "p25_radio" => "P25 Radio", - "p25_net" => "P25 netwerk", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDN netwerk", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Tijd", - "mode" => "Mode", - "callsign" => "Roepletters", - "target" => "Doel", - "src" => "Bron", // Short version of "Source" - "dur" => "Duur", // Short version of "Duration" - "loss" => "Verlies", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Groep", - "logoff" => "Uitloggen", - "info" => "Informatie", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Laatste 20 oproepen gehoord (RX) via deze Gateway", - "local_tx_list" => "Laatste 20 oproepen verzonden (TX) via deze Gateway", - "active_starnet_groups" => "Actieve Starnet groepen", - "active_starnet_members" => "Actieve Starnet groepsleden", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "D-Star Link Informatie", - "service_status" => "Service Status" + // Banner texts + "digital_voice" => "Digital Voice", + "configuration" => "Configuratie", + "dashboard_for" => "Dashboard voor", + // Banner links + "dashboard" => "Dashboard", + "admin" => "Admin", + "power" => "Power", + "update" => "Update", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Reset all", + "live_logs" => "Actuele Logs", + // Config page section headdings + "hardware_info" => "Gateway hardware informatie", + "control_software" => "Controller Host software", + "mmdvmhost_config" => "MMDVMHost configuratie", + "general_config" => "Algemene configuratie", + "dmr_config" => "DMR configuratie", + "dstar_config" => "D-Star configuratie", + "ysf_config" => "Yaesu System Fusion configuratie", + "p25_config" => "P25 configuratie", + "nxdn_config" => "NXDN configuratie", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG configuratie", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wireless configuratie", + "fw_config" => "Firewall configuratie", + "remote_access_pw" => "Remote Access paswoord", + // Config Page - Section General + "setting" => "Instelling", + "value" => "Waarde", + "apply" => "Toepassen", + // Config Page - Gateway Hardware Information + "hostname" => "Hostnaam", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller software", + "controller_mode" => "Controller modus", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR modus", + "d-star_mode" => "D-Star modus", + "ysf_mode" => "YSF modus", + "p25_mode" => "P25 modus", + "nxdn_mode" => "NXDN modus", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM display type", + "mode_hangtime" => "Mode hangtijd", + // Config Page - General Configuration + "node_call" => "Node roepletters", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio frequentie", + "lattitude" => "Breedtegraad", + "longitude" => "Lengtegraad", + "town" => "Plaats", + "country" => "Land", + "url" => "URL", + "radio_type" => "Radio/Modem type", + "node_type" => "Node type", + "timezone" => "Systeem tijdzone", + "dash_lang" => "Dashboard taal", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister netwerk", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ netwerk", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master AAN", + "dmr_cc" => "DMR kleur code (CC)", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 roepletters", + "dstar_rpt2" => "RPT2 roepletters", + "dstar_irc_password" => "ircDDBGateway paswoord", + "dstar_default_ref" => "Standaard reflector", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway taal", + "dstar_irc_time" => "Tijd uitzenden", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF standaard Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 standaard Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN standaard Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Dashboard toegang", + "fw_irc" => "ircDDBGateway op afstand", + "fw_ssh" => "SSH toegang", + // Config Page - Password + "user" => "Gebruikersnaam", + "password" => "Paswoord", + "set_password" => "Voer paswoord in", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Actieve modi", + "net_status" => "Netwerk status", + "internet" => "Internet", + "radio_info" => "Radio info", + "dstar_repeater" => "D-Star repeater", + "dstar_net" => "D-Star netwerk", + "dmr_repeater" => "DMR repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF netwerk", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 netwerk", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN netwerk", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Tijd", + "mode" => "Mode", + "callsign" => "Roepletters", + "target" => "Doel", + "src" => "Bron", // Short version of "Source" + "dur" => "Duur", // Short version of "Duration" + "loss" => "Verlies", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Groep", + "logoff" => "Uitloggen", + "info" => "Informatie", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Laatste 20 oproepen gehoord (RX) via deze Gateway", + "local_tx_list" => "Laatste 20 oproepen verzonden (TX) via deze Gateway", + "active_starnet_groups" => "Actieve Starnet groepen", + "active_starnet_members" => "Actieve Starnet groepsleden", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Informatie", + "service_status" => "Service Status" ); +?> diff --git a/lang/english_uk.php b/lang/english_uk.php index 7d4b473..fc2d818 100644 --- a/lang/english_uk.php +++ b/lang/english_uk.php @@ -5,152 +5,153 @@ // Updated: 02-Aug-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voice", - "configuration" => "Configuration", - "dashboard_for" => "Dashboard for", - // Banner links - "dashboard" => "Dashboard", - "admin" => "Admin", - "power" => "Power", - "update" => "Update", - "backup_restore" => "Backup/Restore", - "factory_reset" => "Factory Reset", - "live_logs" => "Live Logs", - // Config page section headdings - "hardware_info" => "Gateway Hardware Information", - "control_software" => "Control Software", - "mmdvmhost_config" => "MMDVMHost Configuration", - "general_config" => "General Configuration", - "dmr_config" => "DMR Configuration", - "dstar_config" => "D-Star Configuration", - "ysf_config" => "Yaesu System Fusion Configuration", - "p25_config" => "P25 Configuration", - "nxdn_config" => "NXDN Configuration", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG Configuration", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Wireless Configuration", - "fw_config" => "Firewall Configuration", - "remote_access_pw" => "Remote Access Password", - // Config Page - Section General - "setting" => "Setting", - "value" => "Value", - "apply" => "Apply Changes", - // Config Page - Gateway Hardware Information - "hostname" => "Hostname", - "kernel" => "Kernel", - "platform" => "Platform", - "cpu_load" => "CPU Load", - "cpu_temp" => "CPU Temp", - // Config Page - Control Software - "controller_software" => "Controller Software", - "controller_mode" => "Controller Mode", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Mode", - "d-star_mode" => "D-Star Mode", - "ysf_mode" => "YSF Mode", - "p25_mode" => "P25 Mode", - "nxdn_mode" => "NXDN Mode", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Display Type", - "mode_hangtime" => "Mode Hangtime", - // Config Page - General Configuration - "node_call" => "Node Callsign", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Radio Frequency", - "lattitude" => "Latitude", - "longitude" => "Longitude", - "town" => "Town", - "country" => "Country", - "url" => "URL", - "radio_type" => "Radio/Modem Type", - "node_type" => "Node Type", - "timezone" => "System Time Zone", - "dash_lang" => "Dashboard Language", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister Network", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ Network", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Enable", - "dmr_cc" => "DMR Colour Code", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 Callsign", - "dstar_rpt2" => "RPT2 Callsign", - "dstar_irc_password" => "Remote Password", - "dstar_default_ref" => "Default Reflector", - "aprs_host" => "APRS Host", - "dstar_irc_lang" => "ircDDBGateway Language", - "dstar_irc_time" => "Time Announcements", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF Startup Host", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 Startup Host", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN Startup Host", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Dashboard Access", - "fw_irc" => "ircDDBGateway Remote", - "fw_ssh" => "SSH Access", - // Config Page - Password - "user" => "User Name", - "password" => "Password", - "set_password" => "Set Password", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Modes Enabled", - "net_status" => "Network Status", - "internet" => "Internet", - "radio_info" => "Radio Info", - "dstar_repeater" => "D-Star Repeater", - "dstar_net" => "D-Star Network", - "dmr_repeater" => "DMR Repeater", - "dmr_master" => "DMR Master", - "ysf_net" => "YSF Network", - "p25_radio" => "P25 Radio", - "p25_net" => "P25 Network", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDN Network", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Time", - "mode" => "Mode", - "callsign" => "Callsign", - "target" => "Target", - "src" => "Src", // Short version of "Source" - "dur" => "Dur", // Short version of "Duration" - "loss" => "Loss", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Group", - "logoff" => "LogOff", - "info" => "Information", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Gateway Activity", - "local_tx_list" => "Local RF Activity", - "active_starnet_groups" => "Active Starnet Groups", - "active_starnet_members" => "Active Starnet Group Members", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "D-Star Link Information", - "service_status" => "Service Status" + // Banner texts + "digital_voice" => "Digital Voice", + "configuration" => "Configuration", + "dashboard_for" => "Dashboard for", + // Banner links + "dashboard" => "Dashboard", + "admin" => "Admin", + "power" => "Power", + "update" => "Update", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Factory Reset", + "live_logs" => "Live Logs", + // Config page section headdings + "hardware_info" => "Gateway Hardware Information", + "control_software" => "Control Software", + "mmdvmhost_config" => "MMDVMHost Configuration", + "general_config" => "General Configuration", + "dmr_config" => "DMR Configuration", + "dstar_config" => "D-Star Configuration", + "ysf_config" => "Yaesu System Fusion Configuration", + "p25_config" => "P25 Configuration", + "nxdn_config" => "NXDN Configuration", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Configuration", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wireless Configuration", + "fw_config" => "Firewall Configuration", + "remote_access_pw" => "Remote Access Password", + // Config Page - Section General + "setting" => "Setting", + "value" => "Value", + "apply" => "Apply Changes", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller Software", + "controller_mode" => "Controller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Display Type", + "mode_hangtime" => "Mode Hangtime", + // Config Page - General Configuration + "node_call" => "Node Callsign", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frequency", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Town", + "country" => "Country", + "url" => "URL", + "radio_type" => "Radio/Modem Type", + "node_type" => "Node Type", + "timezone" => "System Time Zone", + "dash_lang" => "Dashboard Language", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Colour Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Callsign", + "dstar_rpt2" => "RPT2 Callsign", + "dstar_irc_password" => "Remote Password", + "dstar_default_ref" => "Default Reflector", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Language", + "dstar_irc_time" => "Time Announcements", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startup Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startup Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startup Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Dashboard Access", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH Access", + // Config Page - Password + "user" => "User Name", + "password" => "Password", + "set_password" => "Set Password", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes Enabled", + "net_status" => "Network Status", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Network", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Network", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Network", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Network", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Time", + "mode" => "Mode", + "callsign" => "Callsign", + "target" => "Target", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Group", + "logoff" => "LogOff", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Gateway Activity", + "local_tx_list" => "Local RF Activity", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Information", + "service_status" => "Service Status" ); +?> diff --git a/lang/english_us.php b/lang/english_us.php index ac4a523..9a9610f 100644 --- a/lang/english_us.php +++ b/lang/english_us.php @@ -5,152 +5,153 @@ // Updated: 02-Aug-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voice", - "configuration" => "Configuration", - "dashboard_for" => "Dashboard for", - // Banner links - "dashboard" => "Dashboard", - "admin" => "Admin", - "power" => "Power", - "update" => "Update", - "backup_restore" => "Backup/Restore", - "factory_reset" => "Factory Reset", - "live_logs" => "Live Logs", - // Config page section headdings - "hardware_info" => "Gateway Hardware Information", - "control_software" => "Control Software", - "mmdvmhost_config" => "MMDVMHost Configuration", - "general_config" => "General Configuration", - "dmr_config" => "DMR Configuration", - "dstar_config" => "D-Star Configuration", - "ysf_config" => "Yaesu System Fusion Configuration", - "p25_config" => "P25 Configuration", - "nxdn_config" => "NXDN Configuration", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG Configuration", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Wireless Configuration", - "fw_config" => "Firewall Configuration", - "remote_access_pw" => "Remote Access Password", - // Config Page - Section General - "setting" => "Setting", - "value" => "Value", - "apply" => "Apply Changes", - // Config Page - Gateway Hardware Information - "hostname" => "Hostname", - "kernel" => "Kernel", - "platform" => "Platform", - "cpu_load" => "CPU Load", - "cpu_temp" => "CPU Temp", - // Config Page - Control Software - "controller_software" => "Controller Software", - "controller_mode" => "Controller Mode", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Mode", - "d-star_mode" => "D-Star Mode", - "ysf_mode" => "YSF Mode", - "p25_mode" => "P25 Mode", - "nxdn_mode" => "NXDN Mode", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Display Type", - "mode_hangtime" => "Mode Hangtime", - // Config Page - General Configuration - "node_call" => "Node Callsign", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Radio Frequency", - "lattitude" => "Latitude", - "longitude" => "Longitude", - "town" => "Town", - "country" => "Country", - "url" => "URL", - "radio_type" => "Radio/Modem Type", - "node_type" => "Node Type", - "timezone" => "System Time Zone", - "dash_lang" => "Dashboard Language", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister Network", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ Network", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Enable", - "dmr_cc" => "DMR Color Code", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 Callsign", - "dstar_rpt2" => "RPT2 Callsign", - "dstar_irc_password" => "Remote Password", - "dstar_default_ref" => "Default Reflector", - "aprs_host" => "APRS Host", - "dstar_irc_lang" => "ircDDBGateway Language", - "dstar_irc_time" => "Time Announcements", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF Startup Host", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 Startup Host", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN Startup Host", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Dashboard Access", - "fw_irc" => "ircDDBGateway Remote", - "fw_ssh" => "SSH Access", - // Config Page - Password - "user" => "User Name", - "password" => "Password", - "set_password" => "Set Password", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Modes Enabled", - "net_status" => "Network Status", - "internet" => "Internet", - "radio_info" => "Radio Info", - "dstar_repeater" => "D-Star Repeater", - "dstar_net" => "D-Star Network", - "dmr_repeater" => "DMR Repeater", - "dmr_master" => "DMR Master", - "ysf_net" => "YSF Network", - "p25_radio" => "P25 Radio", - "p25_net" => "P25 Network", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDN Network", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Time", - "mode" => "Mode", - "callsign" => "Callsign", - "target" => "Target", - "src" => "Src", // Short version of "Source" - "dur" => "Dur", // Short version of "Duration" - "loss" => "Loss", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Group", - "logoff" => "LogOff", - "info" => "Information", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Gateway Activity", - "local_tx_list" => "Local RF Activity", - "active_starnet_groups" => "Active Starnet Groups", - "active_starnet_members" => "Active Starnet Group Members", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "D-Star Link Information", - "service_status" => "Service Status" + // Banner texts + "digital_voice" => "Digital Voice", + "configuration" => "Configuration", + "dashboard_for" => "Dashboard for", + // Banner links + "dashboard" => "Dashboard", + "admin" => "Admin", + "power" => "Power", + "update" => "Update", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Factory Reset", + "live_logs" => "Live Logs", + // Config page section headdings + "hardware_info" => "Gateway Hardware Information", + "control_software" => "Control Software", + "mmdvmhost_config" => "MMDVMHost Configuration", + "general_config" => "General Configuration", + "dmr_config" => "DMR Configuration", + "dstar_config" => "D-Star Configuration", + "ysf_config" => "Yaesu System Fusion Configuration", + "p25_config" => "P25 Configuration", + "nxdn_config" => "NXDN Configuration", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Configuration", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wireless Configuration", + "fw_config" => "Firewall Configuration", + "remote_access_pw" => "Remote Access Password", + // Config Page - Section General + "setting" => "Setting", + "value" => "Value", + "apply" => "Apply Changes", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller Software", + "controller_mode" => "Controller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Display Type", + "mode_hangtime" => "Mode Hangtime", + // Config Page - General Configuration + "node_call" => "Node Callsign", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frequency", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Town", + "country" => "Country", + "url" => "URL", + "radio_type" => "Radio/Modem Type", + "node_type" => "Node Type", + "timezone" => "System Time Zone", + "dash_lang" => "Dashboard Language", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Color Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Callsign", + "dstar_rpt2" => "RPT2 Callsign", + "dstar_irc_password" => "Remote Password", + "dstar_default_ref" => "Default Reflector", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Language", + "dstar_irc_time" => "Time Announcements", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startup Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startup Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startup Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Dashboard Access", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH Access", + // Config Page - Password + "user" => "User Name", + "password" => "Password", + "set_password" => "Set Password", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes Enabled", + "net_status" => "Network Status", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Network", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Network", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Network", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Network", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Time", + "mode" => "Mode", + "callsign" => "Callsign", + "target" => "Target", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Group", + "logoff" => "LogOff", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Gateway Activity", + "local_tx_list" => "Local RF Activity", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Information", + "service_status" => "Service Status" ); +?> diff --git a/lang/french_fr.php b/lang/french_fr.php index bdb534a..6af05fb 100644 --- a/lang/french_fr.php +++ b/lang/french_fr.php @@ -5,152 +5,153 @@ // Updated: 01-Nov-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Relais numérique", - "configuration" => "Configuration", - "dashboard_for" => "Console pour", - // Banner links - "dashboard" => "Console", - "admin" => "Administration", - "power" => "Arrêt/Redémarrage", - "update" => "Mise à jour", - "backup_restore" => "Sauvegarde/Restauration", - "factory_reset" => "Réinitialisation Usine", - "live_logs" => "Surveillance des Logs", - // Config page section headdings - "hardware_info" => "Informations matérielles de la passerelle", - "control_software" => "Contrôle logiciel", - "mmdvmhost_config" => "Configuration de MMDVMHost", - "general_config" => "Configuration générale", - "dmr_config" => "Configuration DMR", - "dstar_config" => "Configuration D-STAR", - "ysf_config" => "Configuration Yaesu System Fusion", - "p25_config" => "Configuration P25", - "nxdn_config" => "Configuration NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "Configuration POCSAG", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Configuration Réseau WIFI", - "fw_config" => "Configuration du Firewall", - "remote_access_pw" => "Mot de passe accès distant", - // Config Page - Section General - "setting" => "Paramètres", - "value" => "Valeur", - "apply" => "Appliquer les modifications", - // Config Page - Gateway Hardware Information - "hostname" => "Nom d'hôte", - "kernel" => "Kernel", - "platform" => "Plateforme", - "cpu_load" => "Charge CPU", - "cpu_temp" => "Température CPU", - // Config Page - Control Software - "controller_software" => "Logiciel controleur", - "controller_mode" => "Mode controleur", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Mode DMR", - "d-star_mode" => "Mode D-Star", - "ysf_mode" => "Mode YSF", - "p25_mode" => "Mode P25", - "nxdn_mode" => "Mode NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "Afficheur MMDVM", - "mode_hangtime" => "Mode Hangtime", - // Config Page - General Configuration - "node_call" => "Indicatif du Node", - "dmr_id" => "Id CCS7/DMR", - "radio_freq" => "Fréquence radio", - "lattitude" => "Latitude", - "longitude" => "Longitude", - "town" => "Ville", - "country" => "Pays", - "url" => "URL", - "radio_type" => "Modèle Radio/Modem", - "node_type" => "Type de Node", - "timezone" => "Fuseau horaire", - "dash_lang" => "Langage de la console", - // Config Page - DMR Configuration - "dmr_master" => "Master DMR(MMDVMHost)", - "bm_master" => "Master BrandMeister", - "bm_network" => "Réseau BrandMeister", - "dmr_plus_master" => "Master DMR+", - "dmr_plus_network" => "Réseau DMR+", - "xlx_master" => "Master XLX", - "xlx_enable" => "Master XLX actif", - "dmr_cc" => "Code Couleur DMR", - "dmr_embeddedlconly" => "DMR LC intégré uniquement", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "Indicatif RPT1", - "dstar_rpt2" => "Indicatif RPT2", - "dstar_irc_password" => "Mot de passe ircDDBGateway", - "dstar_default_ref" => "Reflecteur par défaut", - "aprs_host" => "Hôte APRS", - "dstar_irc_lang" => "Langage ircDDBGateway", - "dstar_irc_time" => "Annonces horaires", - // Config Page - YSF Configuration - "ysf_startup_host" => "Room YSF au démarrage", - // Config Page - P25 Configuration - "p25_startup_host" => "Hôte de démarrage P25", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "Hôte de démarrage NXDN", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Accès Console", - "fw_irc" => "Commande à distance ircDDBGateway", - "fw_ssh" => "Accès SSH", - // Config Page - Password - "user" => "Nom d'utilisateur", - "password" => "Mot de passe", - "set_password" => "Définir le mot de passe", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Modes actifs", - "net_status" => "État du réseau", - "internet" => "Internet", - "radio_info" => "Info Radio", - "dstar_repeater" => "Relais D-Star", - "dstar_net" => "Réseau D-Star", - "dmr_repeater" => "Relais DMR", - "dmr_master" => "Master DMR", - "ysf_net" => "Réseau YSF", - "p25_radio" => "Radio P25", - "p25_net" => "Réseau P25", - "nxdn_radio" => "Radio NXDN", - "nxdn_net" => "Réseau NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Heure", - "mode" => "Mode", - "callsign" => "Indicatif ", - "target" => "Cible", - "src" => "Source ", // Short version of "Source" - "dur" => "Durée ", // Short version of "Duration" - "loss" => "Pertes", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Groupe", - "logoff" => "Déconnexion", - "info" => "Information", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Activité de la passerelle", - "local_tx_list" => "Activité locale de la voie radio", - "active_starnet_groups" => "Active Starnet Groups", - "active_starnet_members" => "Active Starnet Group Members", - "d-star_link_manager" => "Administrateur du lien D-Star", - "d-star_link_status" => "Informations du lien D-Star", - "service_status" => "État du service" + // Banner texts + "digital_voice" => "Relais numérique", + "configuration" => "Configuration", + "dashboard_for" => "Console pour", + // Banner links + "dashboard" => "Console", + "admin" => "Administration", + "power" => "Arrêt/Redémarrage", + "update" => "Mise à jour", + "backup_restore" => "Sauvegarde/Restauration", + "factory_reset" => "Réinitialisation Usine", + "live_logs" => "Surveillance des Logs", + // Config page section headdings + "hardware_info" => "Informations matérielles de la passerelle", + "control_software" => "Contrôle logiciel", + "mmdvmhost_config" => "Configuration de MMDVMHost", + "general_config" => "Configuration générale", + "dmr_config" => "Configuration DMR", + "dstar_config" => "Configuration D-STAR", + "ysf_config" => "Configuration Yaesu System Fusion", + "p25_config" => "Configuration P25", + "nxdn_config" => "Configuration NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuration POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuration Réseau WIFI", + "fw_config" => "Configuration du Firewall", + "remote_access_pw" => "Mot de passe accès distant", + // Config Page - Section General + "setting" => "Paramètres", + "value" => "Valeur", + "apply" => "Appliquer les modifications", + // Config Page - Gateway Hardware Information + "hostname" => "Nom d'hôte", + "kernel" => "Kernel", + "platform" => "Plateforme", + "cpu_load" => "Charge CPU", + "cpu_temp" => "Température CPU", + // Config Page - Control Software + "controller_software" => "Logiciel controleur", + "controller_mode" => "Mode controleur", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Mode DMR", + "d-star_mode" => "Mode D-Star", + "ysf_mode" => "Mode YSF", + "p25_mode" => "Mode P25", + "nxdn_mode" => "Mode NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Afficheur MMDVM", + "mode_hangtime" => "Mode Hangtime", + // Config Page - General Configuration + "node_call" => "Indicatif du Node", + "dmr_id" => "Id CCS7/DMR", + "radio_freq" => "Fréquence radio", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Ville", + "country" => "Pays", + "url" => "URL", + "radio_type" => "Modèle Radio/Modem", + "node_type" => "Type de Node", + "timezone" => "Fuseau horaire", + "dash_lang" => "Langage de la console", + // Config Page - DMR Configuration + "dmr_master" => "Master DMR(MMDVMHost)", + "bm_master" => "Master BrandMeister", + "bm_network" => "Réseau BrandMeister", + "dmr_plus_master" => "Master DMR+", + "dmr_plus_network" => "Réseau DMR+", + "xlx_master" => "Master XLX", + "xlx_enable" => "Master XLX actif", + "dmr_cc" => "Code Couleur DMR", + "dmr_embeddedlconly" => "DMR LC intégré uniquement", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Indicatif RPT1", + "dstar_rpt2" => "Indicatif RPT2", + "dstar_irc_password" => "Mot de passe ircDDBGateway", + "dstar_default_ref" => "Reflecteur par défaut", + "aprs_host" => "Hôte APRS", + "dstar_irc_lang" => "Langage ircDDBGateway", + "dstar_irc_time" => "Annonces horaires", + // Config Page - YSF Configuration + "ysf_startup_host" => "Room YSF au démarrage", + // Config Page - P25 Configuration + "p25_startup_host" => "Hôte de démarrage P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Hôte de démarrage NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Accès Console", + "fw_irc" => "Commande à distance ircDDBGateway", + "fw_ssh" => "Accès SSH", + // Config Page - Password + "user" => "Nom d'utilisateur", + "password" => "Mot de passe", + "set_password" => "Définir le mot de passe", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes actifs", + "net_status" => "État du réseau", + "internet" => "Internet", + "radio_info" => "Info Radio", + "dstar_repeater" => "Relais D-Star", + "dstar_net" => "Réseau D-Star", + "dmr_repeater" => "Relais DMR", + "dmr_master" => "Master DMR", + "ysf_net" => "Réseau YSF", + "p25_radio" => "Radio P25", + "p25_net" => "Réseau P25", + "nxdn_radio" => "Radio NXDN", + "nxdn_net" => "Réseau NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Heure", + "mode" => "Mode", + "callsign" => "Indicatif ", + "target" => "Cible", + "src" => "Source ", // Short version of "Source" + "dur" => "Durée ", // Short version of "Duration" + "loss" => "Pertes", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Groupe", + "logoff" => "Déconnexion", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Activité de la passerelle", + "local_tx_list" => "Activité locale de la voie radio", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "Administrateur du lien D-Star", + "d-star_link_status" => "Informations du lien D-Star", + "service_status" => "État du service" ); +?> diff --git a/lang/german_de.php b/lang/german_de.php index 1d1142f..1c2de46 100644 --- a/lang/german_de.php +++ b/lang/german_de.php @@ -5,152 +5,153 @@ // 08-Aug-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voice", - "configuration" => "Konfiguration", - "dashboard_for" => "Tableau für", - // Banner links - "dashboard" => "Tableau", - "admin" => "Admin", - "power" => "Strom", - "update" => "Aktualisieren", - "backup_restore" => "Datensicherung/Wiederherstellung", - "factory_reset" => "Werkseinstellung", - "live_logs" => "Protokoll", - // Config page section headdings - "hardware_info" => "Gateway Hardware Information", - "control_software" => "Kontrollsoftware", - "mmdvmhost_config" => "MMDVMHost Konfiguration", - "general_config" => "Basis Konfiguration", - "dmr_config" => "DMR Konfiguration", - "dstar_config" => "D-Star Konfiguration", - "ysf_config" => "Yaesu System Fusion Konfiguration", - "p25_config" => "P25 Konfiguration", - "nxdn_config" => "NXDN Konfiguration", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG Konfiguration", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Wlan Konfiguration", - "fw_config" => "Firewall Konfiguration", - "remote_access_pw" => "Fernzugriff", - // Config Page - Section General - "setting" => "Einstellung", - "value" => "Wert", - "apply" => "Speichern", - // Config Page - Gateway Hardware Information - "hostname" => "Rechnername", - "kernel" => "Kernel", - "platform" => "Plattform", - "cpu_load" => "CPU Last", - "cpu_temp" => "CPU Temp", - // Config Page - Control Software - "controller_software" => "Kontroller Software", - "controller_mode" => "Kontroller Mode", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Modus", - "d-star_mode" => "D-Star Modus", - "ysf_mode" => "YSF Modus", - "p25_mode" => "P25 Modus", - "nxdn_mode" => "NXDN Modus", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Display Typ", - "mode_hangtime" => "Mode Nachlaufzeit", - // Config Page - General Configuration - "node_call" => "Node Rufzeichen", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Radio Frequenz", - "lattitude" => "Breitengrad", - "longitude" => "Längengrad", - "town" => "Stadt", - "country" => "Land", - "url" => "URL", - "radio_type" => "Radio/Modem Typ", - "node_type" => "Node Typ", - "timezone" => "Systemzeit Zone", - "dash_lang" => "Tableau Sprache", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister Netzwerk", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ Netzwerk", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Aktiv", - "dmr_cc" => "DMR Color Code", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 Rufzeichen", - "dstar_rpt2" => "RPT2 Rufzeichen", - "dstar_irc_password" => "ircDDBGateway Passwort", - "dstar_default_ref" => "Standard Reflektor", - "aprs_host" => "APRS Host", - "dstar_irc_lang" => "ircDDBGateway Sprache", - "dstar_irc_time" => "Zeit Ansagen", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF Startup Host", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 Startup Host", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN Startup Host", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Tableau Zugriff", - "fw_irc" => "ircDDBGateway Remote", - "fw_ssh" => "SSH Zugriff", - // Config Page - Password - "user" => "Benutzername", - "password" => "Passwort", - "set_password" => "Passwort setzen", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Aktive Modi", - "net_status" => "Netzwerk Status", - "internet" => "Internet", - "radio_info" => "Radio Info", - "dstar_repeater" => "D-Star Relais", - "dstar_net" => "D-Star Netzwerk", - "dmr_repeater" => "DMR Relais", - "dmr_master" => "DMR Master", - "ysf_net" => "YSF Netzwerk", - "p25_radio" => "P25 Radio", - "p25_net" => "P25 Netzwerk", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDN Netzwerk", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Zeit", - "mode" => "Mode", - "callsign" => "Rufzeichen", - "target" => "Ziel", - "src" => "Quelle", // Short version of "Source" - "dur" => "Dauer", // Short version of "Duration" - "loss" => "Verlust", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Gruppe", - "logoff" => "LogOff", - "info" => "Information", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Letzten 20 Rufzeichen, die gehört wurden", - "local_tx_list" => "Letzten 20 Rufzeichen, die dieses Gateway nutzten", - "active_starnet_groups" => "Aktive Starnet Gruppen", - "active_starnet_members" => "Aktive Starnet Gruppen Mitglieder", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "D-Star Link Information", - "service_status" => "Service Status" - ); + // Banner texts + "digital_voice" => "Digital Voice", + "configuration" => "Konfiguration", + "dashboard_for" => "Tableau für", + // Banner links + "dashboard" => "Tableau", + "admin" => "Admin", + "power" => "Strom", + "update" => "Aktualisieren", + "backup_restore" => "Datensicherung/Wiederherstellung", + "factory_reset" => "Werkseinstellung", + "live_logs" => "Protokoll", + // Config page section headdings + "hardware_info" => "Gateway Hardware Information", + "control_software" => "Kontrollsoftware", + "mmdvmhost_config" => "MMDVMHost Konfiguration", + "general_config" => "Basis Konfiguration", + "dmr_config" => "DMR Konfiguration", + "dstar_config" => "D-Star Konfiguration", + "ysf_config" => "Yaesu System Fusion Konfiguration", + "p25_config" => "P25 Konfiguration", + "nxdn_config" => "NXDN Konfiguration", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Konfiguration", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wlan Konfiguration", + "fw_config" => "Firewall Konfiguration", + "remote_access_pw" => "Fernzugriff", + // Config Page - Section General + "setting" => "Einstellung", + "value" => "Wert", + "apply" => "Speichern", + // Config Page - Gateway Hardware Information + "hostname" => "Rechnername", + "kernel" => "Kernel", + "platform" => "Plattform", + "cpu_load" => "CPU Last", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Kontroller Software", + "controller_mode" => "Kontroller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Modus", + "d-star_mode" => "D-Star Modus", + "ysf_mode" => "YSF Modus", + "p25_mode" => "P25 Modus", + "nxdn_mode" => "NXDN Modus", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Display Typ", + "mode_hangtime" => "Mode Nachlaufzeit", + // Config Page - General Configuration + "node_call" => "Node Rufzeichen", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frequenz", + "lattitude" => "Breitengrad", + "longitude" => "Längengrad", + "town" => "Stadt", + "country" => "Land", + "url" => "URL", + "radio_type" => "Radio/Modem Typ", + "node_type" => "Node Typ", + "timezone" => "Systemzeit Zone", + "dash_lang" => "Tableau Sprache", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Netzwerk", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Netzwerk", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Aktiv", + "dmr_cc" => "DMR Color Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Rufzeichen", + "dstar_rpt2" => "RPT2 Rufzeichen", + "dstar_irc_password" => "ircDDBGateway Passwort", + "dstar_default_ref" => "Standard Reflektor", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Sprache", + "dstar_irc_time" => "Zeit Ansagen", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startup Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startup Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startup Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Tableau Zugriff", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH Zugriff", + // Config Page - Password + "user" => "Benutzername", + "password" => "Passwort", + "set_password" => "Passwort setzen", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Aktive Modi", + "net_status" => "Netzwerk Status", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Relais", + "dstar_net" => "D-Star Netzwerk", + "dmr_repeater" => "DMR Relais", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Netzwerk", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Netzwerk", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Netzwerk", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Zeit", + "mode" => "Mode", + "callsign" => "Rufzeichen", + "target" => "Ziel", + "src" => "Quelle", // Short version of "Source" + "dur" => "Dauer", // Short version of "Duration" + "loss" => "Verlust", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Gruppe", + "logoff" => "LogOff", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Letzten 20 Rufzeichen, die gehört wurden", + "local_tx_list" => "Letzten 20 Rufzeichen, die dieses Gateway nutzten", + "active_starnet_groups" => "Aktive Starnet Gruppen", + "active_starnet_members" => "Aktive Starnet Gruppen Mitglieder", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Information", + "service_status" => "Service Status" + ); +?> diff --git a/lang/greek_gr.php b/lang/greek_gr.php index c5051a1..02bb182 100644 --- a/lang/greek_gr.php +++ b/lang/greek_gr.php @@ -5,152 +5,153 @@ // Updated: 06-Aug-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Ψηφιακή Τηλεφωνία", - "configuration" => "Ρυθμίσεις", - "dashboard_for" => "Πίνακας Ελέγχου για τον", - // Banner links - "dashboard" => "Πίνακας Ελέγχου", - "admin" => "Διαχείριση", - "power" => "Απενεργοποίηση", - "update" => "Ενημέρωση", - "backup_restore" => "Εφεδρικό Αντίγραφο/Επαναφορά", - "factory_reset" => "Εργοστασιακές Ρυθμίσεις", - "live_logs" => "Αρχείο Καταγραφής", - // Config page section headdings - "hardware_info" => "Πληροφορίες Υλικού Πύλης", - "control_software" => "Πρόγραμμα Ελέγχου", - "mmdvmhost_config" => "Ρυθμίσεις του MMDVMHost", - "general_config" => "Γενικές Ρυθμίσεις", - "dmr_config" => "Ρυθμίσεις DMR", - "dstar_config" => "Ρυθμίσεις D-Star", - "ysf_config" => "Ρυθμίσεις Fusion", - "p25_config" => "Ρυθμίσεις P25", - "nxdn_config" => "Ρυθμίσεις NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "Ρυθμίσεις POCSAG", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Ρυθμίσεις WiFi", - "fw_config" => "Ρυθμίσεις Τείχους Προστασίας", - "remote_access_pw" => "Κωδικός Πρόσβασης", - // Config Page - Section General - "setting" => "Ρυθμίσεις", - "value" => "Τιμή", - "apply" => "Εφαρμογή", - // Config Page - Gateway Hardware Information - "hostname" => "Ονομα Συσκευής", - "kernel" => "Πυρήνας", - "platform" => "Πλατφόρμα", - "cpu_load" => "Φόρτος CPU", - "cpu_temp" => "Θερμοκρασία CPU", - // Config Page - Control Software - "controller_software" => "Πρόγραμμα Ελεγκτή", - "controller_mode" => "Κατάσταση Ελεγκτή", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Λειτουργία DMR", - "d-star_mode" => "Λειτουργία D-Star", - "ysf_mode" => "Λειτουργία YSF", - "p25_mode" => "Λειτουργία P25", - "nxdn_mode" => "Λειτουργία NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "Τύπος Οθόνης MMDVM", - "mode_hangtime" => "Χρόνος Επαναφοράς Σάρωσης", - // Config Page - General Configuration - "node_call" => "Διακριτικό Κόμβου", - "dmr_id" => "Ταυτότητα CCS7/DMR", - "radio_freq" => "Συχνότητα", - "lattitude" => "Γεωγραφικό Πλάτος", - "longitude" => "Γεωγραφικό Μήκος", - "town" => "Πόλη", - "country" => "Χώρα", - "url" => "URL", - "radio_type" => "Τύπος Modem", - "node_type" => "Τύπος Κόμβου", - "timezone" => "Ζώνη Ωρας", - "dash_lang" => "Γλώσσα Πίνακα Ελέγχου", - // Config Page - DMR Configuration - "dmr_master" => "Εξυπηρετητής DMR (MMDVMHost)", - "bm_master" => "Εξυπηρετητής BrandMeister", - "bm_network" => "Δίκτυο BrandMeister", - "dmr_plus_master" => "Εξυπηρετητής DMR+", - "dmr_plus_network" => "Δίκτυο DMR+", - "xlx_master" => "Εξυπηρετητής XLX", - "xlx_enable" => "Ενεργοποίηση Εξυπηρετητή XLX", - "dmr_cc" => "Κωδικός Χρώματος DMR", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "Διακριτικό RPT1", - "dstar_rpt2" => "Διακριτικό RPT2", - "dstar_irc_password" => "Κωδικός ircDDBGateway", - "dstar_default_ref" => "Reflector Προεπιλογής", - "aprs_host" => "Κεντρικός Υπολ. APRS", - "dstar_irc_lang" => "Γλώσσα ircDDBGateway", - "dstar_irc_time" => "Αναγγελίες Ωρας", - // Config Page - YSF Configuration - "ysf_startup_host" => "Εξυπηρετητής Εκκίνησης YSF", - // Config Page - P25 Configuration - "p25_startup_host" => "Εξυπηρετητής Εκκίνησης P25", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "Εξυπηρετητής Εκκίνησης NXDN", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Πρόσβαση στον Πίνακα Ελέγχου", - "fw_irc" => "Απομακρυσμένος ircDDBGateway", - "fw_ssh" => "Πρόσβαση SSH", - // Config Page - Password - "user" => "Ονομα Χρήστη", - "password" => "Κωδικός Πρόσβασης", - "set_password" => "Αλλαγή Κωδικού Πρόσβασης", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Ενεργές Λειτουργίες", - "net_status" => "Κατάσταση Δικτύου", - "internet" => "Διαδίκτυο", - "radio_info" => "Πληροφ. Ασυρμάτου", - "dstar_repeater" => "Αναμεταδότης D-Star", - "dstar_net" => "Δίκτυο D-Star", - "dmr_repeater" => "Αναμεταδότης DMR", - "dmr_master" => "Εξυπηρετητής DMR", - "ysf_net" => "Δίκτυο YSF", - "p25_radio" => "Ασύρματος P25", - "p25_net" => "Δίκτυο P25", - "nxdn_radio" => "Ασύρματος NXDN", - "nxdn_net" => "Δίκτυο NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Ωρα", - "mode" => "Λειτουργία", - "callsign" => "Διακριτικό", - "target" => "Προορισμός", - "src" => "Πηγή", // Short version of "Source" - "dur" => "Διάρκεια", // Short version of "Duration" - "loss" => "Απώλεια", - "ber" => "Σφάλματα", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Ομάδα", - "logoff" => "Αποσύνδεση", - "info" => "Πληροφορίες", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Τελευταία 20 διακριτικά που ακούστηκαν μέσω αυτής της Πύλης", - "local_tx_list" => "Τελευταία 20 διακριτικά που είχαν πρόσβαση σε αυτή την Πύλη", - "active_starnet_groups" => "Ενεργές Ομάδες Starnet", - "active_starnet_members" => "Ενεργά Μέλη Ομάδων Starnet", - "d-star_link_manager" => "Διαχειριστής Ζεύζης D-Star", - "d-star_link_status" => "Πληροφορίες Ζεύξης D-Star", - "service_status" => "Κατάσταση Υπηρεσίας" + // Banner texts + "digital_voice" => "Ψηφιακή Τηλεφωνία", + "configuration" => "Ρυθμίσεις", + "dashboard_for" => "Πίνακας Ελέγχου για τον", + // Banner links + "dashboard" => "Πίνακας Ελέγχου", + "admin" => "Διαχείριση", + "power" => "Απενεργοποίηση", + "update" => "Ενημέρωση", + "backup_restore" => "Εφεδρικό Αντίγραφο/Επαναφορά", + "factory_reset" => "Εργοστασιακές Ρυθμίσεις", + "live_logs" => "Αρχείο Καταγραφής", + // Config page section headdings + "hardware_info" => "Πληροφορίες Υλικού Πύλης", + "control_software" => "Πρόγραμμα Ελέγχου", + "mmdvmhost_config" => "Ρυθμίσεις του MMDVMHost", + "general_config" => "Γενικές Ρυθμίσεις", + "dmr_config" => "Ρυθμίσεις DMR", + "dstar_config" => "Ρυθμίσεις D-Star", + "ysf_config" => "Ρυθμίσεις Fusion", + "p25_config" => "Ρυθμίσεις P25", + "nxdn_config" => "Ρυθμίσεις NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Ρυθμίσεις POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Ρυθμίσεις WiFi", + "fw_config" => "Ρυθμίσεις Τείχους Προστασίας", + "remote_access_pw" => "Κωδικός Πρόσβασης", + // Config Page - Section General + "setting" => "Ρυθμίσεις", + "value" => "Τιμή", + "apply" => "Εφαρμογή", + // Config Page - Gateway Hardware Information + "hostname" => "Ονομα Συσκευής", + "kernel" => "Πυρήνας", + "platform" => "Πλατφόρμα", + "cpu_load" => "Φόρτος CPU", + "cpu_temp" => "Θερμοκρασία CPU", + // Config Page - Control Software + "controller_software" => "Πρόγραμμα Ελεγκτή", + "controller_mode" => "Κατάσταση Ελεγκτή", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Λειτουργία DMR", + "d-star_mode" => "Λειτουργία D-Star", + "ysf_mode" => "Λειτουργία YSF", + "p25_mode" => "Λειτουργία P25", + "nxdn_mode" => "Λειτουργία NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Τύπος Οθόνης MMDVM", + "mode_hangtime" => "Χρόνος Επαναφοράς Σάρωσης", + // Config Page - General Configuration + "node_call" => "Διακριτικό Κόμβου", + "dmr_id" => "Ταυτότητα CCS7/DMR", + "radio_freq" => "Συχνότητα", + "lattitude" => "Γεωγραφικό Πλάτος", + "longitude" => "Γεωγραφικό Μήκος", + "town" => "Πόλη", + "country" => "Χώρα", + "url" => "URL", + "radio_type" => "Τύπος Modem", + "node_type" => "Τύπος Κόμβου", + "timezone" => "Ζώνη Ωρας", + "dash_lang" => "Γλώσσα Πίνακα Ελέγχου", + // Config Page - DMR Configuration + "dmr_master" => "Εξυπηρετητής DMR (MMDVMHost)", + "bm_master" => "Εξυπηρετητής BrandMeister", + "bm_network" => "Δίκτυο BrandMeister", + "dmr_plus_master" => "Εξυπηρετητής DMR+", + "dmr_plus_network" => "Δίκτυο DMR+", + "xlx_master" => "Εξυπηρετητής XLX", + "xlx_enable" => "Ενεργοποίηση Εξυπηρετητή XLX", + "dmr_cc" => "Κωδικός Χρώματος DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Διακριτικό RPT1", + "dstar_rpt2" => "Διακριτικό RPT2", + "dstar_irc_password" => "Κωδικός ircDDBGateway", + "dstar_default_ref" => "Reflector Προεπιλογής", + "aprs_host" => "Κεντρικός Υπολ. APRS", + "dstar_irc_lang" => "Γλώσσα ircDDBGateway", + "dstar_irc_time" => "Αναγγελίες Ωρας", + // Config Page - YSF Configuration + "ysf_startup_host" => "Εξυπηρετητής Εκκίνησης YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Εξυπηρετητής Εκκίνησης P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Εξυπηρετητής Εκκίνησης NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Πρόσβαση στον Πίνακα Ελέγχου", + "fw_irc" => "Απομακρυσμένος ircDDBGateway", + "fw_ssh" => "Πρόσβαση SSH", + // Config Page - Password + "user" => "Ονομα Χρήστη", + "password" => "Κωδικός Πρόσβασης", + "set_password" => "Αλλαγή Κωδικού Πρόσβασης", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Ενεργές Λειτουργίες", + "net_status" => "Κατάσταση Δικτύου", + "internet" => "Διαδίκτυο", + "radio_info" => "Πληροφ. Ασυρμάτου", + "dstar_repeater" => "Αναμεταδότης D-Star", + "dstar_net" => "Δίκτυο D-Star", + "dmr_repeater" => "Αναμεταδότης DMR", + "dmr_master" => "Εξυπηρετητής DMR", + "ysf_net" => "Δίκτυο YSF", + "p25_radio" => "Ασύρματος P25", + "p25_net" => "Δίκτυο P25", + "nxdn_radio" => "Ασύρματος NXDN", + "nxdn_net" => "Δίκτυο NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Ωρα", + "mode" => "Λειτουργία", + "callsign" => "Διακριτικό", + "target" => "Προορισμός", + "src" => "Πηγή", // Short version of "Source" + "dur" => "Διάρκεια", // Short version of "Duration" + "loss" => "Απώλεια", + "ber" => "Σφάλματα", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Ομάδα", + "logoff" => "Αποσύνδεση", + "info" => "Πληροφορίες", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Τελευταία 20 διακριτικά που ακούστηκαν μέσω αυτής της Πύλης", + "local_tx_list" => "Τελευταία 20 διακριτικά που είχαν πρόσβαση σε αυτή την Πύλη", + "active_starnet_groups" => "Ενεργές Ομάδες Starnet", + "active_starnet_members" => "Ενεργά Μέλη Ομάδων Starnet", + "d-star_link_manager" => "Διαχειριστής Ζεύζης D-Star", + "d-star_link_status" => "Πληροφορίες Ζεύξης D-Star", + "service_status" => "Κατάσταση Υπηρεσίας" ); +?> diff --git a/lang/hungarian_hu.php b/lang/hungarian_hu.php index 2f0ad9b..5cb8937 100644 --- a/lang/hungarian_hu.php +++ b/lang/hungarian_hu.php @@ -5,152 +5,153 @@ // Updated: 07-Mar-2024 // $lang = array ( - // Banner texts - "digital_voice" => "Digitális", - "configuration" => "Konfiguráció", - "dashboard_for" => "Irányítópult", - // Banner links - "dashboard" => "Irányítópult", - "admin" => "Admin", - "power" => "Tápellátás", - "update" => "Frissítés", - "backup_restore" => "Mentés/Visszaállítás", - "factory_reset" => "Gyári beállítás", - "live_logs" => "Élő forgalom", - // Config page section headdings - "hardware_info" => "Hardver információ", - "control_software" => "Vezérlő szoftver", - "mmdvmhost_config" => "MMDVMHost konfiguráció", - "general_config" => "Általános konfiguráció", - "dmr_config" => "DMR konfiguráció", - "dstar_config" => "D-Star konfiguráció", - "ysf_config" => "Yaesu System Fusion konfiguráció", - "p25_config" => "P25 konfiguráció", - "nxdn_config" => "NXDN konfiguráció", - "m17_config" => "M17 konfiguráció", - "pocsag_config" => "POCSAG konfiguráció", - "mobilegps_config" => "Mobil GPS konfiguráció", - "wifi_config" => "Wi-fi konfiguráció", - "fw_config" => "Tűzfal konfiguráció", - "remote_access_pw" => "Távoli hozzáférés jelszó", - // Config Page - Section General - "setting" => "Beállítás", - "value" => "Érték", - "apply" => "Alkalmaz", - // Config Page - Gateway Hardware Information - "hostname" => "Kiszolgáló neve", - "kernel" => "Kernel", - "platform" => "Rendszer", - "cpu_load" => "CPU Terhelés", - "cpu_temp" => "CPU Hőmérséklet", - // Config Page - Control Software - "controller_software" => "Vezérlő Szoftver", - "controller_mode" => "Mód", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Mód", - "d-star_mode" => "D-Star Mód", - "ysf_mode" => "YSF Mód", - "p25_mode" => "P25 Mód", - "nxdn_mode" => "NXDN Mód", - "m17_mode" => "M17 Mód", - "mmdvm_display" => "MMDVM kijelző típusa", - "mode_hangtime" => "Mód tartási ideje", - // Config Page - General Configuration - "node_call" => "Hívójel", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Frekvencia", - "lattitude" => "Szélességi kör", - "longitude" => "Hosszúsági kör", - "town" => "Város", - "country" => "Ország", - "url" => "URL", - "radio_type" => "Rádió/Modem típusa", - "node_type" => "Hozzáférési pont típusa", - "timezone" => "Időzóna", - "dash_lang" => "Irányítópult nyelve", - // Config Page - DMR Configuration - "dmr_master" => "DMR Szerver (MMDVMHost)", - "bm_master" => "BrandMeister Szerver", - "bm_network" => "BrandMeister Hálózat", - "dmr_plus_master" => "DMR+ Szerver", - "dmr_plus_network" => "DMR+ Hálózat", - "xlx_master" => "XLX Szerver", - "xlx_enable" => "XLX Szerver engedélyezése", - "dmr_cc" => "DMR Color kód", - "dmr_embeddedlconly" => "DMR GPS/Talker Alias kikapcsolása", - "dmr_dumptadata" => "DMR GPS/Talker Alias mentése logba", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 Hívójel", - "dstar_rpt2" => "RPT2 Hívójel", - "dstar_irc_password" => "Jelszó", - "dstar_default_ref" => "Alapértelmezett reflektor", - "aprs_host" => "APRS", - "dstar_irc_lang" => "ircDDBGateway Nyelv", - "dstar_irc_time" => "Idő hirdetmények", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF kiszolgáló", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 kiszolgáló", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN kiszolgáló", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 kiszolgáló", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "Mobil GPS", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Sebessége", - // Config Page - Firewall Configuration - "fw_dash" => "Irányítópult hozzáférés", - "fw_irc" => "ircDDBGateway távoli hozzáférés", - "fw_ssh" => "SSH hozzáférés", - // Config Page - Password - "user" => "Felhasználónév", - "password" => "Jelszó", - "set_password" => "Beállítás", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Bekapcsolt módok", - "net_status" => "Hálózat státusza", - "internet" => "Internet", - "radio_info" => "Rádió infó", - "dstar_repeater" => "D-Star átjátszó", - "dstar_net" => "D-Star hálózat", - "dmr_repeater" => "DMR átjátszó", - "dmr_master" => "DMR hálózat", - "ysf_net" => "YSF hálózat", - "p25_radio" => "P25 rádió", - "p25_net" => "P25 hálózat", - "nxdn_radio" => "NXDN rádió", - "nxdn_net" => "NXDN hálózat", - "m17_radio" => "M17 rádió", - "m17_net" => "M17 hálózat", - // Dashboard Front Page - Calls - "time" => "Idő", - "mode" => "Mód", - "callsign" => "Hívójel", - "target" => "Cél", - "src" => "Forrás", // Short version of "Source" - "dur" => "Hossz", // Short version of "Duration" - "loss" => "Veszteség", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET aktivitás", - "pocsag_timeslot" => "Időrés", - "pocsag_msg" => "Üzenet", - // Dashboard - Extra Info - "group" => "Csoport", - "logoff" => "LogOff", - "info" => "Információ", - "utot" => "FIT", // Short for User Timeout - "gtot" => "CSIT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Átjáró aktivitás", - "local_tx_list" => "Helyi RF aktivitás", - "active_starnet_groups" => "Aktív Starnet csoport", - "active_starnet_members" => "Aktív Starnet csoport résztvevők", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "D-Star Link Információ", - "service_status" => "Szolgáltatás állapota" + // Banner texts + "digital_voice" => "Digitális", + "configuration" => "Konfiguráció", + "dashboard_for" => "Irányítópult", + // Banner links + "dashboard" => "Irányítópult", + "admin" => "Admin", + "power" => "Tápellátás", + "update" => "Frissítés", + "backup_restore" => "Mentés/Visszaállítás", + "factory_reset" => "Gyári beállítás", + "live_logs" => "Élő forgalom", + // Config page section headdings + "hardware_info" => "Hardver információ", + "control_software" => "Vezérlő szoftver", + "mmdvmhost_config" => "MMDVMHost konfiguráció", + "general_config" => "Általános konfiguráció", + "dmr_config" => "DMR konfiguráció", + "dstar_config" => "D-Star konfiguráció", + "ysf_config" => "Yaesu System Fusion konfiguráció", + "p25_config" => "P25 konfiguráció", + "nxdn_config" => "NXDN konfiguráció", + "m17_config" => "M17 konfiguráció", + "pocsag_config" => "POCSAG konfiguráció", + "mobilegps_config" => "Mobil GPS konfiguráció", + "wifi_config" => "Wi-fi konfiguráció", + "fw_config" => "Tűzfal konfiguráció", + "remote_access_pw" => "Távoli hozzáférés jelszó", + // Config Page - Section General + "setting" => "Beállítás", + "value" => "Érték", + "apply" => "Alkalmaz", + // Config Page - Gateway Hardware Information + "hostname" => "Kiszolgáló neve", + "kernel" => "Kernel", + "platform" => "Rendszer", + "cpu_load" => "CPU Terhelés", + "cpu_temp" => "CPU Hőmérséklet", + // Config Page - Control Software + "controller_software" => "Vezérlő Szoftver", + "controller_mode" => "Mód", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mód", + "d-star_mode" => "D-Star Mód", + "ysf_mode" => "YSF Mód", + "p25_mode" => "P25 Mód", + "nxdn_mode" => "NXDN Mód", + "m17_mode" => "M17 Mód", + "mmdvm_display" => "MMDVM kijelző típusa", + "mode_hangtime" => "Mód tartási ideje", + // Config Page - General Configuration + "node_call" => "Hívójel", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frekvencia", + "lattitude" => "Szélességi kör", + "longitude" => "Hosszúsági kör", + "town" => "Város", + "country" => "Ország", + "url" => "URL", + "radio_type" => "Rádió/Modem típusa", + "node_type" => "Hozzáférési pont típusa", + "timezone" => "Időzóna", + "dash_lang" => "Irányítópult nyelve", + // Config Page - DMR Configuration + "dmr_master" => "DMR Szerver (MMDVMHost)", + "bm_master" => "BrandMeister Szerver", + "bm_network" => "BrandMeister Hálózat", + "dmr_plus_master" => "DMR+ Szerver", + "dmr_plus_network" => "DMR+ Hálózat", + "xlx_master" => "XLX Szerver", + "xlx_enable" => "XLX Szerver engedélyezése", + "dmr_cc" => "DMR Color kód", + "dmr_embeddedlconly" => "DMR GPS/Talker Alias kikapcsolása", + "dmr_dumptadata" => "DMR GPS/Talker Alias mentése logba", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Hívójel", + "dstar_rpt2" => "RPT2 Hívójel", + "dstar_irc_password" => "Jelszó", + "dstar_default_ref" => "Alapértelmezett reflektor", + "aprs_host" => "APRS", + "dstar_irc_lang" => "ircDDBGateway Nyelv", + "dstar_irc_time" => "Idő hirdetmények", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF kiszolgáló", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 kiszolgáló", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN kiszolgáló", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 kiszolgáló", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "Mobil GPS", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Sebessége", + // Config Page - Firewall Configuration + "fw_dash" => "Irányítópult hozzáférés", + "fw_irc" => "ircDDBGateway távoli hozzáférés", + "fw_ssh" => "SSH hozzáférés", + // Config Page - Password + "user" => "Felhasználónév", + "password" => "Jelszó", + "set_password" => "Beállítás", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Bekapcsolt módok", + "net_status" => "Hálózat státusza", + "internet" => "Internet", + "radio_info" => "Rádió infó", + "dstar_repeater" => "D-Star átjátszó", + "dstar_net" => "D-Star hálózat", + "dmr_repeater" => "DMR átjátszó", + "dmr_master" => "DMR hálózat", + "ysf_net" => "YSF hálózat", + "p25_radio" => "P25 rádió", + "p25_net" => "P25 hálózat", + "nxdn_radio" => "NXDN rádió", + "nxdn_net" => "NXDN hálózat", + "m17_radio" => "M17 rádió", + "m17_net" => "M17 hálózat", + // Dashboard Front Page - Calls + "time" => "Idő", + "mode" => "Mód", + "callsign" => "Hívójel", + "target" => "Cél", + "src" => "Forrás", // Short version of "Source" + "dur" => "Hossz", // Short version of "Duration" + "loss" => "Veszteség", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET aktivitás", + "pocsag_timeslot" => "Időrés", + "pocsag_msg" => "Üzenet", + // Dashboard - Extra Info + "group" => "Csoport", + "logoff" => "LogOff", + "info" => "Információ", + "utot" => "FIT", // Short for User Timeout + "gtot" => "CSIT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Átjáró aktivitás", + "local_tx_list" => "Helyi RF aktivitás", + "active_starnet_groups" => "Aktív Starnet csoport", + "active_starnet_members" => "Aktív Starnet csoport résztvevők", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Információ", + "service_status" => "Szolgáltatás állapota" ); +?> diff --git a/lang/index.php b/lang/index.php index 702d3d1..8b13789 100644 --- a/lang/index.php +++ b/lang/index.php @@ -1,3 +1 @@ - "Modi Digitali", - "configuration" => "Configurazioni", - "dashboard_for" => "Cruscotto", - // Banner links - "dashboard" => "Cruscotto", - "admin" => "Admin", - "power" => "Power", - "update" => "Aggiornamento", - "backup_restore" => "Backup/Restore", - "factory_reset" => "Ripristino", - "live_logs" => "Live Logs", - // Config page section headdings - "hardware_info" => "Informazioni Hardware del Gateway", - "control_software" => "Software di controllo", - "mmdvmhost_config" => "MMDVMHost Config", - "general_config" => "Configurazione Generale", - "dmr_config" => "DMR Config", - "dstar_config" => "D-Star Configuration", - "ysf_config" => "Yaesu System Fusion Config", - "p25_config" => "P25 Config", - "nxdn_config" => "NXDN Config", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG Config", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Wireless Config", - "fw_config" => "Firewall Config", - "remote_access_pw" => "Password Accesso Remoto", - // Config Page - Section General - "setting" => "Settaggi", - "value" => "Valori", - "apply" => "Applicare le modifiche", - // Config Page - Gateway Hardware Information - "hostname" => "Hostname", - "kernel" => "Kernel", - "platform" => "Platform", - "cpu_load" => "CPU Load", - "cpu_temp" => "CPU Temp", - // Config Page - Control Software - "controller_software" => "Controller Software", - "controller_mode" => "Controller Mode", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Mode", - "d-star_mode" => "D-Star Mode", - "ysf_mode" => "YSF Mode", - "p25_mode" => "P25 Mode", - "nxdn_mode" => "NXDN Mode", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Display Type", - "mode_hangtime" => "Tempo Ritardo", - // Config Page - General Configuration - "node_call" => "Nominativo", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Frequenza Radio", - "lattitude" => "Latitudine", - "longitude" => "Longitudine", - "town" => "Città", - "country" => "Stato", - "url" => "URL", - "radio_type" => "Radio/Modem Modello", - "node_type" => "Tipo di Nodo", - "timezone" => "Fuso Orario", - "dash_lang" => "Linguaggio Cruscotto", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister Network", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ Network", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Attivo", - "dmr_cc" => "DMR Colour Code", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "Nominativo RPT1", - "dstar_rpt2" => "Nominativo RPT2", - "dstar_irc_password" => "ircDDBGateway Password", - "dstar_default_ref" => "Default Reflector", - "aprs_host" => "APRS Host", - "dstar_irc_lang" => "ircDDBGateway Linguaggio", - "dstar_irc_time" => "Annuncio (Vocale) Orario", - // Config Page - YSF Configuration - "ysf_startup_host" => "Room YSF Di Partenza", - // Config Page - P25 Configuration - "p25_startup_host" => "Room P25 Di Partenza", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "Room NXDN Di Partenza", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Accesso Cruscotto", - "fw_irc" => "ircDDBGateway Remote", - "fw_ssh" => "Accesso SSH", - // Config Page - Password - "user" => "Nome Utente", - "password" => "Password", - "set_password" => "Imposta Password", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Modi Attivi", - "net_status" => "Stato Rete", - "internet" => "Internet", - "radio_info" => "Info Radio", - "dstar_repeater" => "D-Star Repeater", - "dstar_net" => "D-Star Network", - "dmr_repeater" => "DMR Repeater", - "dmr_master" => "DMR Master", - "ysf_net" => "YSF Network", - "p25_radio" => "P25 Radio", - "p25_net" => "P25 Network", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDN Network", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Ora", - "mode" => "Modo", - "callsign" => "Nominativo", - "target" => "Target", - "src" => "Src", // Short version of "Source" - "dur" => "Dur", // Short version of "Duration" - "loss" => "Loss", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Gruppo", - "logoff" => "LogOff", - "info" => "Informazioni", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Le Ultime 20 Trasmissioni Di Questo Nodo", - "local_tx_list" => "Gli Ultimi 20 Accessi RF Su Questo Nodo", - "active_starnet_groups" => "Gruppi Attivi Starnet", - "active_starnet_members" => "Menbri Attivi Nel Gruppo Starnet", - "d-star_link_manager" => "Gestione D-Star Link", - "d-star_link_status" => "Info D-Star Link", - "service_status" => "Stato Servizi" + // Banner texts + "digital_voice" => "Modi Digitali", + "configuration" => "Configurazioni", + "dashboard_for" => "Cruscotto", + // Banner links + "dashboard" => "Cruscotto", + "admin" => "Admin", + "power" => "Power", + "update" => "Aggiornamento", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Ripristino", + "live_logs" => "Live Logs", + // Config page section headdings + "hardware_info" => "Informazioni Hardware del Gateway", + "control_software" => "Software di controllo", + "mmdvmhost_config" => "MMDVMHost Config", + "general_config" => "Configurazione Generale", + "dmr_config" => "DMR Config", + "dstar_config" => "D-Star Configuration", + "ysf_config" => "Yaesu System Fusion Config", + "p25_config" => "P25 Config", + "nxdn_config" => "NXDN Config", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Config", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Wireless Config", + "fw_config" => "Firewall Config", + "remote_access_pw" => "Password Accesso Remoto", + // Config Page - Section General + "setting" => "Settaggi", + "value" => "Valori", + "apply" => "Applicare le modifiche", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller Software", + "controller_mode" => "Controller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Display Type", + "mode_hangtime" => "Tempo Ritardo", + // Config Page - General Configuration + "node_call" => "Nominativo", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frequenza Radio", + "lattitude" => "Latitudine", + "longitude" => "Longitudine", + "town" => "Città", + "country" => "Stato", + "url" => "URL", + "radio_type" => "Radio/Modem Modello", + "node_type" => "Tipo di Nodo", + "timezone" => "Fuso Orario", + "dash_lang" => "Linguaggio Cruscotto", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Attivo", + "dmr_cc" => "DMR Colour Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Nominativo RPT1", + "dstar_rpt2" => "Nominativo RPT2", + "dstar_irc_password" => "ircDDBGateway Password", + "dstar_default_ref" => "Default Reflector", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Linguaggio", + "dstar_irc_time" => "Annuncio (Vocale) Orario", + // Config Page - YSF Configuration + "ysf_startup_host" => "Room YSF Di Partenza", + // Config Page - P25 Configuration + "p25_startup_host" => "Room P25 Di Partenza", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Room NXDN Di Partenza", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Accesso Cruscotto", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "Accesso SSH", + // Config Page - Password + "user" => "Nome Utente", + "password" => "Password", + "set_password" => "Imposta Password", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modi Attivi", + "net_status" => "Stato Rete", + "internet" => "Internet", + "radio_info" => "Info Radio", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Network", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Network", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Network", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Network", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Ora", + "mode" => "Modo", + "callsign" => "Nominativo", + "target" => "Target", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Gruppo", + "logoff" => "LogOff", + "info" => "Informazioni", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Le Ultime 20 Trasmissioni Di Questo Nodo", + "local_tx_list" => "Gli Ultimi 20 Accessi RF Su Questo Nodo", + "active_starnet_groups" => "Gruppi Attivi Starnet", + "active_starnet_members" => "Menbri Attivi Nel Gruppo Starnet", + "d-star_link_manager" => "Gestione D-Star Link", + "d-star_link_status" => "Info D-Star Link", + "service_status" => "Stato Servizi" ); +?> diff --git a/lang/japanese_jp.php b/lang/japanese_jp.php index 0cd2ae1..ae6b068 100644 --- a/lang/japanese_jp.php +++ b/lang/japanese_jp.php @@ -7,152 +7,153 @@ // Updated: 10-Jan-2021 // $lang = array ( - // Banner texts - "digital_voice" => "デジタルボイス", - "configuration" => "設定", - "dashboard_for" => "ダッシュボード for", - // Banner links - "dashboard" => "ダッシュボード", - "admin" => "制御", - "power" => "電源", - "update" => "更新", - "backup_restore" => "バックアップ/復旧", - "factory_reset" => "工場出荷に戻る", - "live_logs" => "ログ", - // Config page section headdings - "hardware_info" => "ゲートウェイハード情報", - "control_software" => "制御ソフトウェア", - "mmdvmhost_config" => "MMDVMHost設定", - "general_config" => "全般設定", - "dmr_config" => "DMR設定", - "dstar_config" => "D-Star設定", - "ysf_config" => "YSF設定", - "p25_config" => "P25設定", - "nxdn_config" => "NXDN設定", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG設定", - "mobilegps_config" => "外部GPS設定", - "wifi_config" => "無線LAN設定", - "fw_config" => "ファイアウォール設定", - "remote_access_pw" => "遠隔ログインパスワード", - // Config Page - Section General - "setting" => "設定項目", - "value" => "設定内容", - "apply" => "更新", - // Config Page - Gateway Hardware Information - "hostname" => "ホスト名", - "kernel" => "カーネル", - "platform" => "マイコン", - "cpu_load" => "CPU負荷", - "cpu_temp" => "CPU温度", - // Config Page - Control Software - "controller_software" => "制御ソフト", - "controller_mode" => "制御モード", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMRモード", - "d-star_mode" => "D-Starモード", - "ysf_mode" => "YSFモード", - "p25_mode" => "P25モード", - "nxdn_mode" => "NXDNモード", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVMディスプレイタイプ", - "mode_hangtime" => "モード保持時間", - // Config Page - General Configuration - "node_call" => "ノード コールサイン", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "周波数", - "lattitude" => "緯度", - "longitude" => "経度", - "town" => "市町村", - "country" => "国", - "url" => "URL", - "radio_type" => "Radio/Modem タイプ", - "node_type" => "ノードタイプ", - "timezone" => "タイムゾーン", - "dash_lang" => "言語", - // Config Page - DMR Configuration - "dmr_master" => "DMRマスター(MMDVMHost)", - "bm_master" => "BrandMeisterマスター", - "bm_network" => "BrandMeisterネットワーク", - "dmr_plus_master" => "DMR+マスター", - "dmr_plus_network" => "DMR+ネットワーク", - "xlx_master" => "XLXマスター", - "xlx_enable" => "XLXマスター有効", - "dmr_cc" => "DMRカラーコード", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1コールサイン", - "dstar_rpt2" => "RPT2コールサイン", - "dstar_irc_password" => "ircDDBGatewayパスワード", - "dstar_default_ref" => "初期接続リフレクター", - "aprs_host" => "APRSホスト", - "dstar_irc_lang" => "ircDDBGateway言語", - "dstar_irc_time" => "時刻アナウンス", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF初期接続ホスト", - // Config Page - P25 Configuration - "p25_startup_host" => "P25初期接続ホスト", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN初期接続ホスト", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "外部GPS有効", - "mobilegps_port" => "GPSポート", - "mobilegps_speed" => "GPSポート速度", - // Config Page - Firewall Configuration - "fw_dash" => "ダッシュボードアクセス", - "fw_irc" => "ircDDBGatewayリモート", - "fw_ssh" => "SSHアクセス", - // Config Page - Password - "user" => "ユーザー名", - "password" => "パスワード", - "set_password" => "パスワード保存", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "使用可能モード", - "net_status" => "ネットワーク状況", - "internet" => "インターネット", - "radio_info" => "無線モデム情報", - "dstar_repeater" => "D-Starレピーター", - "dstar_net" => "D-Starネットワーク", - "dmr_repeater" => "DMRレピーター", - "dmr_master" => "DMRマスター", - "ysf_net" => "YSFネットワーク", - "p25_radio" => "P25 Radio", - "p25_net" => "P25ネットワーク", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDNネットワーク", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "時刻", - "mode" => "モード", - "callsign" => "コールサイン", - "target" => "ターゲット", - "src" => "ソース", // Short version of "Source" - "dur" => "時間", // Short version of "Duration" - "loss" => "ロス", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNETゲートウェイ状態", - "pocsag_timeslot" => "タイムスロット", - "pocsag_msg" => "メッセージ", - // Dashboard - Extra Info - "group" => "グループ", - "logoff" => "ログオフ", - "info" => "情報", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "受信リスト(最新20局)", - "local_tx_list" => "送信リスト(最新20局)", - "active_starnet_groups" => "Active Starnet Groups", - "active_starnet_members" => "Active Starnet Group Members", - "d-star_link_manager" => "D-Star接続マネージャー", - "d-star_link_status" => "D-Star接続情報", - "service_status" => "サービス状態" + // Banner texts + "digital_voice" => "デジタルボイス", + "configuration" => "設定", + "dashboard_for" => "ダッシュボード for", + // Banner links + "dashboard" => "ダッシュボード", + "admin" => "制御", + "power" => "電源", + "update" => "更新", + "backup_restore" => "バックアップ/復旧", + "factory_reset" => "工場出荷に戻る", + "live_logs" => "ログ", + // Config page section headdings + "hardware_info" => "ゲートウェイハード情報", + "control_software" => "制御ソフトウェア", + "mmdvmhost_config" => "MMDVMHost設定", + "general_config" => "全般設定", + "dmr_config" => "DMR設定", + "dstar_config" => "D-Star設定", + "ysf_config" => "YSF設定", + "p25_config" => "P25設定", + "nxdn_config" => "NXDN設定", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG設定", + "mobilegps_config" => "外部GPS設定", + "wifi_config" => "無線LAN設定", + "fw_config" => "ファイアウォール設定", + "remote_access_pw" => "遠隔ログインパスワード", + // Config Page - Section General + "setting" => "設定項目", + "value" => "設定内容", + "apply" => "更新", + // Config Page - Gateway Hardware Information + "hostname" => "ホスト名", + "kernel" => "カーネル", + "platform" => "マイコン", + "cpu_load" => "CPU負荷", + "cpu_temp" => "CPU温度", + // Config Page - Control Software + "controller_software" => "制御ソフト", + "controller_mode" => "制御モード", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMRモード", + "d-star_mode" => "D-Starモード", + "ysf_mode" => "YSFモード", + "p25_mode" => "P25モード", + "nxdn_mode" => "NXDNモード", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVMディスプレイタイプ", + "mode_hangtime" => "モード保持時間", + // Config Page - General Configuration + "node_call" => "ノード コールサイン", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "周波数", + "lattitude" => "緯度", + "longitude" => "経度", + "town" => "市町村", + "country" => "国", + "url" => "URL", + "radio_type" => "Radio/Modem タイプ", + "node_type" => "ノードタイプ", + "timezone" => "タイムゾーン", + "dash_lang" => "言語", + // Config Page - DMR Configuration + "dmr_master" => "DMRマスター(MMDVMHost)", + "bm_master" => "BrandMeisterマスター", + "bm_network" => "BrandMeisterネットワーク", + "dmr_plus_master" => "DMR+マスター", + "dmr_plus_network" => "DMR+ネットワーク", + "xlx_master" => "XLXマスター", + "xlx_enable" => "XLXマスター有効", + "dmr_cc" => "DMRカラーコード", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1コールサイン", + "dstar_rpt2" => "RPT2コールサイン", + "dstar_irc_password" => "ircDDBGatewayパスワード", + "dstar_default_ref" => "初期接続リフレクター", + "aprs_host" => "APRSホスト", + "dstar_irc_lang" => "ircDDBGateway言語", + "dstar_irc_time" => "時刻アナウンス", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF初期接続ホスト", + // Config Page - P25 Configuration + "p25_startup_host" => "P25初期接続ホスト", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN初期接続ホスト", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "外部GPS有効", + "mobilegps_port" => "GPSポート", + "mobilegps_speed" => "GPSポート速度", + // Config Page - Firewall Configuration + "fw_dash" => "ダッシュボードアクセス", + "fw_irc" => "ircDDBGatewayリモート", + "fw_ssh" => "SSHアクセス", + // Config Page - Password + "user" => "ユーザー名", + "password" => "パスワード", + "set_password" => "パスワード保存", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "使用可能モード", + "net_status" => "ネットワーク状況", + "internet" => "インターネット", + "radio_info" => "無線モデム情報", + "dstar_repeater" => "D-Starレピーター", + "dstar_net" => "D-Starネットワーク", + "dmr_repeater" => "DMRレピーター", + "dmr_master" => "DMRマスター", + "ysf_net" => "YSFネットワーク", + "p25_radio" => "P25 Radio", + "p25_net" => "P25ネットワーク", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDNネットワーク", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "時刻", + "mode" => "モード", + "callsign" => "コールサイン", + "target" => "ターゲット", + "src" => "ソース", // Short version of "Source" + "dur" => "時間", // Short version of "Duration" + "loss" => "ロス", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNETゲートウェイ状態", + "pocsag_timeslot" => "タイムスロット", + "pocsag_msg" => "メッセージ", + // Dashboard - Extra Info + "group" => "グループ", + "logoff" => "ログオフ", + "info" => "情報", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "受信リスト(最新20局)", + "local_tx_list" => "送信リスト(最新20局)", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "D-Star接続マネージャー", + "d-star_link_status" => "D-Star接続情報", + "service_status" => "サービス状態" ); +?> diff --git a/lang/norwegian_no.php b/lang/norwegian_no.php index 1b52c72..23f6983 100644 --- a/lang/norwegian_no.php +++ b/lang/norwegian_no.php @@ -5,152 +5,153 @@ // Updated: 02-Aug-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voice", - "configuration" => "Konfigurasjon", - "dashboard_for" => "Skrivebord for", - // Banner links - "dashboard" => "Skrivebord", - "admin" => "Admin", - "power" => "Strøm", - "update" => "Oppdater", - "backup_restore" => "Backup/Restore", - "factory_reset" => "Tilbakestill", - "live_logs" => "Live Logg", - // Config page section headdings - "hardware_info" => "Gateway Hardware Informasjon", - "control_software" => "Kontroller Programvare", - "mmdvmhost_config" => "MMDVMHost Konfigurasjon", - "general_config" => "Generel Konfigurasjon", - "dmr_config" => "DMR Konfigurasjon", - "dstar_config" => "D-Star Konfigurasjon", - "ysf_config" => "Yaesu System Fusion Konfigurasjon", - "p25_config" => "P25 Konfigurasjon", - "nxdn_config" => "NXDN Konfigurasjon", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG Konfigurasjon", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Trådløs Konfigurasjon", - "fw_config" => "Firewall Konfigurasjon", - "remote_access_pw" => "Fjerntilgangs passord", - // Config Page - Section General - "setting" => "Innstillinger", - "value" => "Verdi", - "apply" => "Bruk endringer", - // Config Page - Gateway Hardware Information - "hostname" => "Vertsnavn", - "kernel" => "Kernel", - "platform" => "Platform", - "cpu_load" => "CPU-belastning", - "cpu_temp" => "CPU Temp", - // Config Page - Control Software - "controller_software" => "Kontroller Programvare", - "controller_mode" => "Kontroller Mode", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Mode", - "d-star_mode" => "D-Star Mode", - "ysf_mode" => "YSF Mode", - "p25_mode" => "P25 Mode", - "nxdn_mode" => "NXDN Mode", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Skjerm Type", - "mode_hangtime" => "Mode Hangtime", - // Config Page - General Configuration - "node_call" => "Node Kallesignal", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Radio Frekvens", - "lattitude" => "Breddegrad", - "longitude" => "lengdegrad", - "town" => "By", - "country" => "Land", - "url" => "URL", - "radio_type" => "Radio/Modem Type", - "node_type" => "Node Type", - "timezone" => "Tidssone", - "dash_lang" => "Skrivebord Språk", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister Nettverk", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ Nettverk", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Aktivert", - "dmr_cc" => "DMR Farge Kode", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 Kallesignal", - "dstar_rpt2" => "RPT2 Kallesignal", - "dstar_irc_password" => "ircDDBGateway Passord", - "dstar_default_ref" => "Standard Reflektor", - "aprs_host" => "APRS Vert", - "dstar_irc_lang" => "ircDDBGateway Språk", - "dstar_irc_time" => "Tids annonsering", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF Oppstarts Vert", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 Oppstarts Vert", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN Oppstarts Vert", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Skrivebord Adgang", - "fw_irc" => "ircDDBGateway Remote", - "fw_ssh" => "SSH Adgang", - // Config Page - Password - "user" => "Bruker navn", - "password" => "Passord", - "set_password" => "Set Passord", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Modes Aktivert", - "net_status" => "Nettverk Status", - "internet" => "Internett", - "radio_info" => "Radio Info", - "dstar_repeater" => "D-Star Repeater", - "dstar_net" => "D-Star Nettverk", - "dmr_repeater" => "DMR Repeater", - "dmr_master" => "DMR Master", - "ysf_net" => "YSF Nettverk", - "p25_radio" => "P25 Radio", - "p25_net" => "P25 Nettverk", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDN Nettverk", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Tid", - "mode" => "Mode", - "callsign" => "Kallesignal", - "target" => "Destinasjon", - "src" => "Src", // Short version of "Source" - "dur" => "Var", // Short version of "Duration" - "loss" => "Loss", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Gruppe", - "logoff" => "Logg Av", - "info" => "Informasjon", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "De siste 20 anropene hørt via denne Gatewayen", - "local_tx_list" => "De siste 20 anropene som åpnet denne Gatewayen", - "active_starnet_groups" => "Aktive Starnet Grupper", - "active_starnet_members" => "Aktive Starnet Gruppe medlemer", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "D-Star Link Informasjon", - "service_status" => "Service Status" + // Banner texts + "digital_voice" => "Digital Voice", + "configuration" => "Konfigurasjon", + "dashboard_for" => "Skrivebord for", + // Banner links + "dashboard" => "Skrivebord", + "admin" => "Admin", + "power" => "Strøm", + "update" => "Oppdater", + "backup_restore" => "Backup/Restore", + "factory_reset" => "Tilbakestill", + "live_logs" => "Live Logg", + // Config page section headdings + "hardware_info" => "Gateway Hardware Informasjon", + "control_software" => "Kontroller Programvare", + "mmdvmhost_config" => "MMDVMHost Konfigurasjon", + "general_config" => "Generel Konfigurasjon", + "dmr_config" => "DMR Konfigurasjon", + "dstar_config" => "D-Star Konfigurasjon", + "ysf_config" => "Yaesu System Fusion Konfigurasjon", + "p25_config" => "P25 Konfigurasjon", + "nxdn_config" => "NXDN Konfigurasjon", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Konfigurasjon", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Trådløs Konfigurasjon", + "fw_config" => "Firewall Konfigurasjon", + "remote_access_pw" => "Fjerntilgangs passord", + // Config Page - Section General + "setting" => "Innstillinger", + "value" => "Verdi", + "apply" => "Bruk endringer", + // Config Page - Gateway Hardware Information + "hostname" => "Vertsnavn", + "kernel" => "Kernel", + "platform" => "Platform", + "cpu_load" => "CPU-belastning", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Kontroller Programvare", + "controller_mode" => "Kontroller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Skjerm Type", + "mode_hangtime" => "Mode Hangtime", + // Config Page - General Configuration + "node_call" => "Node Kallesignal", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frekvens", + "lattitude" => "Breddegrad", + "longitude" => "lengdegrad", + "town" => "By", + "country" => "Land", + "url" => "URL", + "radio_type" => "Radio/Modem Type", + "node_type" => "Node Type", + "timezone" => "Tidssone", + "dash_lang" => "Skrivebord Språk", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Nettverk", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Nettverk", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Aktivert", + "dmr_cc" => "DMR Farge Kode", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Kallesignal", + "dstar_rpt2" => "RPT2 Kallesignal", + "dstar_irc_password" => "ircDDBGateway Passord", + "dstar_default_ref" => "Standard Reflektor", + "aprs_host" => "APRS Vert", + "dstar_irc_lang" => "ircDDBGateway Språk", + "dstar_irc_time" => "Tids annonsering", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Oppstarts Vert", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Oppstarts Vert", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Oppstarts Vert", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Skrivebord Adgang", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH Adgang", + // Config Page - Password + "user" => "Bruker navn", + "password" => "Passord", + "set_password" => "Set Passord", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modes Aktivert", + "net_status" => "Nettverk Status", + "internet" => "Internett", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Nettverk", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Nettverk", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Nettverk", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Nettverk", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Tid", + "mode" => "Mode", + "callsign" => "Kallesignal", + "target" => "Destinasjon", + "src" => "Src", // Short version of "Source" + "dur" => "Var", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Gruppe", + "logoff" => "Logg Av", + "info" => "Informasjon", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "De siste 20 anropene hørt via denne Gatewayen", + "local_tx_list" => "De siste 20 anropene som åpnet denne Gatewayen", + "active_starnet_groups" => "Aktive Starnet Grupper", + "active_starnet_members" => "Aktive Starnet Gruppe medlemer", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Informasjon", + "service_status" => "Service Status" ); +?> diff --git a/lang/polish_pl.php b/lang/polish_pl.php index 204853b..1670385 100644 --- a/lang/polish_pl.php +++ b/lang/polish_pl.php @@ -2,155 +2,156 @@ // // Polish PL Language Pack // Translated 02-Sep-2022 from English Language by Pawel SP8MDH -// Updated 03-Dec-2024 by Pawel SP8MDH +// Edited: 04-Sep-2022 // $lang = array ( - // Banner texts - "digital_voice" => "Tryb cyfrowy", - "configuration" => "Konfiguracja", - "dashboard_for" => "Panel użytkownika", - // Banner links - "dashboard" => "Panel", - "admin" => "Zarządzanie", - "power" => "Zasilanie", - "update" => "Aktualizacja", - "backup_restore" => "Kopia/Przywracanie", - "factory_reset" => "Resetowanie", - "live_logs" => "Logi na żywo", - // Config page section headdings - "hardware_info" => "Informacje sprzętowe bramki", - "control_software" => "Oprogramowanie sterujące", - "mmdvmhost_config" => "Konfiguracja MMDVMHost", - "general_config" => "Konfiguracja główna", - "dmr_config" => "Konfiguracja DMR", - "dstar_config" => "Konfiguracja D-Star", - "ysf_config" => "Konfiguracja Yaesu System Fusion", - "p25_config" => "Konfiguracja P25", - "nxdn_config" => "Konfiguracja NXDN", - "m17_config" => "Konfiguracja M17", - "pocsag_config" => "Konfiguracja POCSAG", - "mobilegps_config" => "Konfiguracja GPS", - "wifi_config" => "Konfiguracja WiFi", - "fw_config" => "Konfiguracja zapory sieciowej", - "remote_access_pw" => "Hasło dostępu zdalnego", - // Config Page - Section General - "setting" => "Ustawienie", - "value" => "Wartość", - "apply" => "Zatwierdź zmiany", - // Config Page - Gateway Hardware Information - "hostname" => "Nazwa hosta", - "kernel" => "Kernel", - "platform" => "Platforma", - "cpu_load" => "Obciążenie CPU", - "cpu_temp" => "Temp. CPU", - // Config Page - Control Software - "controller_software" => "Oprogramowanie kontrolera", - "controller_mode" => "Tryb kontrolera", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Tryb DMR", - "d-star_mode" => "Tryb D-Star", - "ysf_mode" => "Tryb YSF", - "p25_mode" => "Tryb P25", - "nxdn_mode" => "Tryb NXDN", - "m17_mode" => "Tryb M17", - "mmdvm_display" => "Ekran MMDVM", - "mode_hangtime" => "Tryb czasu oczekiwania", - // Config Page - General Configuration - "node_call" => "Znak krótkofalarski bramki", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Częstotliwość radia", - "lattitude" => "Szerokość geograficzna", - "longitude" => "Długość geograficzna", - "town" => "Miejscowość", - "country" => "Państwo", - "url" => "URL", - "radio_type" => "Typ radia/modemu", - "node_type" => "Rodzaj bramki", - "timezone" => "Strefa czasowa", - "dash_lang" => "Język panelu", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "Sieć BrandMeister", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "Sieć DMR+", - "xlx_master" => "XLX Master", - "xlx_enable" => "Włączony XLX Master", - "dmr_cc" => "DMR Colour Code", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "Znak RPT1", - "dstar_rpt2" => "Znak RPT2", - "dstar_irc_password" => "Hasło dostępu zdalnego", - "dstar_default_ref" => "Domyślny reflektor", - "aprs_host" => "Host APRS", - "dstar_irc_lang" => "Język ircDDBGateway", - "dstar_irc_time" => "Czas zapowiedzi", - // Config Page - YSF Configuration - "ysf_startup_host" => "Startowy host YSF", - // Config Page - P25 Configuration - "p25_startup_host" => "Startowy host P25", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "Startowy host NXDN", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "Startowy host M17", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "Włączanie GPS", - "mobilegps_port" => "Port GPS", - "mobilegps_speed" => "Prędkość portu GPS", - // Config Page - Firewall Configuration - "fw_dash" => "Dostęp do panelu", - "fw_irc" => "Zdalny ircDDBGateway", - "fw_ssh" => "Dostęp SSH", - // Config Page - Password - "user" => "Nazwa użytkownika", - "password" => "Hasło", - "set_password" => "Ustaw hasło", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Włączone tryby", - "net_status" => "Status sieci", - "internet" => "Internet", - "radio_info" => "Radio Info", - "dstar_repeater" => "Przemiennik D-Star", - "dstar_net" => "Sieć D-Star", - "dmr_repeater" => "Przemiennik DMR", - "dmr_master" => "DMR Master", - "ysf_net" => "Sieć YSF", - "p25_radio" => "Radio P25", - "p25_net" => "Sieć P25", - "nxdn_radio" => "Radio NXDN", - "nxdn_net" => "Sieć NXDN", - "m17_radio" => "Radio M17", - "m17_net" => "Sieć M17", - // Dashboard Front Page - Calls - "time" => "Czas", - "mode" => "Tryb", - "callsign" => "Znak", - "target" => "Cel", - "src" => "Źródło", - "dur" => "Okres", - "loss" => "Straty", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "Aktywność bramy DAPNET", - "pocsag_timeslot" => "Szczelina czasowa", - "pocsag_msg" => "Wiadomość", - // Dashboard - Extra Info - "group" => "Grupa", - "logoff" => "Wyloguj", - "info" => "Informacja", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Lista ostatnio słyszanych stacji", - "local_tx_list" => "Atywność lokalna", - "active_starnet_groups" => "Aktywne grupy Starnet", - "active_starnet_members" => "Aktywni członkowie grupy Starnet", - "d-star_link_manager" => "Zarządzanie linkami D-Star", - "d-star_link_status" => "Status linków D-Star", - "service_status" => "Status serwisu" + // Banner texts + "digital_voice" => "Tryb cyfrowy", + "configuration" => "Konfiguracja", + "dashboard_for" => "Panel użytkownika", + // Banner links + "dashboard" => "Panel", + "admin" => "Zarządzanie", + "power" => "Zasilanie", + "update" => "Aktualizacja", + "backup_restore" => "Kopia/Przywracanie", + "factory_reset" => "Resetowanie", + "live_logs" => "Logi na żywo", + // Config page section headdings + "hardware_info" => "Informacje sprzętowe bramki", + "control_software" => "Oprogramowanie sterujące", + "mmdvmhost_config" => "Konfiguracja MMDVMHost", + "general_config" => "Konfiguracja główna", + "dmr_config" => "Konfiguracja DMR", + "dstar_config" => "Konfiguracja D-Star", + "ysf_config" => "Konfiguracja Yaesu System Fusion", + "p25_config" => "Konfiguracja P25", + "nxdn_config" => "Konfiguracja NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Konfiguracja POCSAG", + "mobilegps_config" => "Konfiguracja przenośnego GPS", + "wifi_config" => "Konfiguracja WiFi", + "fw_config" => "Konfiguracja zapory sieciowej", + "remote_access_pw" => "Hasło dostępu zdalnego", + // Config Page - Section General + "setting" => "Ustawienie", + "value" => "Wartość", + "apply" => "Zatwierdź zmiany", + // Config Page - Gateway Hardware Information + "hostname" => "Nazwa hosta", + "kernel" => "Kernel", + "platform" => "Platforma", + "cpu_load" => "Obciążenie CPU", + "cpu_temp" => "Temperatura CPU", + // Config Page - Control Software + "controller_software" => "Oprogramowanie kontrolera", + "controller_mode" => "Tryb kontrolera", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Tryb DMR", + "d-star_mode" => "Tryb D-Star", + "ysf_mode" => "Tryb YSF", + "p25_mode" => "Tryb P25", + "nxdn_mode" => "Tryb NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Typ wyświetlacza MMDVM", + "mode_hangtime" => "Tryb czasu oczekiwania", + // Config Page - General Configuration + "node_call" => "Znak krótkofalarski bramki", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Częstotliwość radia", + "lattitude" => "Szerokość geograficzna", + "longitude" => "Długość geograficzna", + "town" => "Miejscowość", + "country" => "Państwo", + "url" => "URL", + "radio_type" => "Typ radia/modemu", + "node_type" => "Rodzaj bramki", + "timezone" => "Strefa czasowa", + "dash_lang" => "Język panelu", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "Sieć BrandMeister", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "Sieć DMR+", + "xlx_master" => "XLX Master", + "xlx_enable" => "Włączony XLX Master", + "dmr_cc" => "DMR Colour Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Znak RPT1", + "dstar_rpt2" => "Znak RPT2", + "dstar_irc_password" => "Hasło dostępu zdalnego", + "dstar_default_ref" => "Domyślny reflektor", + "aprs_host" => "Host APRS", + "dstar_irc_lang" => "Język ircDDBGateway", + "dstar_irc_time" => "Czas zapowiedzi", + // Config Page - YSF Configuration + "ysf_startup_host" => "Startowy host YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Startowy host P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Startowy host NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "Włączanie przenośnego GPS", + "mobilegps_port" => "Port GPS", + "mobilegps_speed" => "Prędkość portu GPS", + // Config Page - Firewall Configuration + "fw_dash" => "Dostęp do panelu", + "fw_irc" => "Zdalny ircDDBGateway", + "fw_ssh" => "Dostęp SSH", + // Config Page - Password + "user" => "Nazwa użytkownika", + "password" => "Hasło", + "set_password" => "Ustaw hasło", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Włączone tryby", + "net_status" => "Status sieci", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "Przemiennik D-Star", + "dstar_net" => "Sieć D-Star", + "dmr_repeater" => "Przemiennik DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "Sieć YSF", + "p25_radio" => "Radio P25", + "p25_net" => "Sieć P25", + "nxdn_radio" => "Radio NXDN", + "nxdn_net" => "Sieć NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Czas", + "mode" => "Tryb", + "callsign" => "Znak", + "target" => "Cel", + "src" => "Źródło", + "dur" => "Okres", + "loss" => "Straty", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "Aktywność bramy DAPNET", + "pocsag_timeslot" => "Szczelina czasowa", + "pocsag_msg" => "Wiadomość", + // Dashboard - Extra Info + "group" => "Grupa", + "logoff" => "Wyloguj", + "info" => "Informacja", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Aktywność bramki", + "local_tx_list" => "Atywność radiowa lokalna", + "active_starnet_groups" => "Aktywne grupy Starnet", + "active_starnet_members" => "Aktywni członkowie grupy Starnet", + "d-star_link_manager" => "Zarządzanie linkami D-Star", + "d-star_link_status" => "Status linków D-Star", + "service_status" => "Status serwisu" ); +?> diff --git a/lang/portuguese_br.php b/lang/portuguese_br.php index 917e50f..f7fe2ec 100644 --- a/lang/portuguese_br.php +++ b/lang/portuguese_br.php @@ -5,152 +5,153 @@ // Updated: 30-Aug-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voz", - "configuration" => "Configuração", - "dashboard_for" => "Painel de Controle de", - // Banner links - "dashboard" => "Painel", - "admin" => "Admin", - "power" => "Ação", - "update" => "Atualizar", - "backup_restore" => "Backup/Restaurar", - "factory_reset" => "Reset", - "live_logs" => "Logs online", - // Config page section headdings - "hardware_info" => "Informações Hardware do Gateway", - "control_software" => "Controle Software", - "mmdvmhost_config" => "MMDVMHost Configuração", - "general_config" => "Configurações Gerais", - "dmr_config" => "Configuração do DMR", - "dstar_config" => "Configuração do D-Star", - "ysf_config" => "Configuração do Sistema Yaesu Fusion", - "p25_config" => "Configuração do P25", - "nxdn_config" => "Configuração do NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "Configuração do POCSAG", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Configuração do Wireless", - "fw_config" => "Configuração do Firewall", - "remote_access_pw" => "Senha do Acesso Remoto", - // Config Page - Section General - "setting" => "Configurações", - "value" => "Valores", - "apply" => "Aplicar", - // Config Page - Gateway Hardware Information - "hostname" => "Nome do Host", - "kernel" => "Kernel", - "platform" => "Plataforma", - "cpu_load" => "Leitura de CPU", - "cpu_temp" => "Temperatura de CPU", - // Config Page - Control Software - "controller_software" => "Tipo de Software", - "controller_mode" => "Modo de Controle", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Modo DMR", - "d-star_mode" => "Modo D-Star", - "ysf_mode" => "Modo YSF", - "p25_mode" => "Modo P25", - "nxdn_mode" => "Modo NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "Exibição MMDVM", - "mode_hangtime" => "Modo Tempo de Espera", - // Config Page - General Configuration - "node_call" => "Indicativo do Node", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Frequencia do Rádio", - "lattitude" => "Latitude", - "longitude" => "Longitude", - "town" => "Cidade", - "country" => "País", - "url" => "URL", - "radio_type" => "Tipo de Radio/Modem", - "node_type" => "Tipo de Node", - "timezone" => "Horário do Sistema", - "dash_lang" => "Idioma do Painel de Controle", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister Rede", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ Network", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Enable", - "dmr_cc" => "Código de Cores DMR", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 Indicativo", - "dstar_rpt2" => "RPT2 Indicativo", - "dstar_irc_password" => "Senha ircDDBGateway", - "dstar_default_ref" => "Refletor Principal", - "aprs_host" => "Servidor APRS", - "dstar_irc_lang" => "Idioma ircDDBGateway", - "dstar_irc_time" => "Anúncio a cada Hora", - // Config Page - YSF Configuration - "ysf_startup_host" => "Servidor Inicial YSF", - // Config Page - P25 Configuration - "p25_startup_host" => "Servidor Inicial P25", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "Servidor Inicial NXDN", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Acesso ao Painel", - "fw_irc" => "Remoto ircDDBGateway", - "fw_ssh" => "Acesso via SSH", - // Config Page - Password - "user" => "Nome do Usuário", - "password" => "Senha", - "set_password" => "Modificar Senha", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Habilitar Modos", - "net_status" => "Status de Rede", - "internet" => "Internet", - "radio_info" => "Info do Rádio", - "dstar_repeater" => "Repetidora D-Star", - "dstar_net" => "Rede D-Star", - "dmr_repeater" => "Repetidora DMR", - "dmr_master" => "DMR Master", - "ysf_net" => "Rede YSF", - "p25_radio" => "Rádio P25", - "p25_net" => "Rede P25", - "nxdn_radio" => "Rádio NDXN", - "nxdn_net" => "Rede NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Hora", - "mode" => "Modo", - "callsign" => "Indicativo", - "target" => "Alvo", - "src" => "Src", // Short version of "Source" - "dur" => "Dur", // Short version of "Duration" - "loss" => "Loss", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Grupo", - "logoff" => "Sair", - "info" => "Informação", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Últimas 20 chamadas via Gateway", - "local_tx_list" => "Últimas 20 chamadas por este Gateway", - "active_starnet_groups" => "Grupo Ativos na Starnet", - "active_starnet_members" => "Grupo de Membros Ativos na Starnet", - "d-star_link_manager" => "Gerenciar Conexão D-Star", - "d-star_link_status" => "Informações do Link D-Star", - "service_status" => "Status do Sistema" + // Banner texts + "digital_voice" => "Digital Voz", + "configuration" => "Configuração", + "dashboard_for" => "Painel de Controle de", + // Banner links + "dashboard" => "Painel", + "admin" => "Admin", + "power" => "Ação", + "update" => "Atualizar", + "backup_restore" => "Backup/Restaurar", + "factory_reset" => "Reset", + "live_logs" => "Logs online", + // Config page section headdings + "hardware_info" => "Informações Hardware do Gateway", + "control_software" => "Controle Software", + "mmdvmhost_config" => "MMDVMHost Configuração", + "general_config" => "Configurações Gerais", + "dmr_config" => "Configuração do DMR", + "dstar_config" => "Configuração do D-Star", + "ysf_config" => "Configuração do Sistema Yaesu Fusion", + "p25_config" => "Configuração do P25", + "nxdn_config" => "Configuração do NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuração do POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuração do Wireless", + "fw_config" => "Configuração do Firewall", + "remote_access_pw" => "Senha do Acesso Remoto", + // Config Page - Section General + "setting" => "Configurações", + "value" => "Valores", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Nome do Host", + "kernel" => "Kernel", + "platform" => "Plataforma", + "cpu_load" => "Leitura de CPU", + "cpu_temp" => "Temperatura de CPU", + // Config Page - Control Software + "controller_software" => "Tipo de Software", + "controller_mode" => "Modo de Controle", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Modo DMR", + "d-star_mode" => "Modo D-Star", + "ysf_mode" => "Modo YSF", + "p25_mode" => "Modo P25", + "nxdn_mode" => "Modo NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Exibição MMDVM", + "mode_hangtime" => "Modo Tempo de Espera", + // Config Page - General Configuration + "node_call" => "Indicativo do Node", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frequencia do Rádio", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Cidade", + "country" => "País", + "url" => "URL", + "radio_type" => "Tipo de Radio/Modem", + "node_type" => "Tipo de Node", + "timezone" => "Horário do Sistema", + "dash_lang" => "Idioma do Painel de Controle", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Rede", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "Código de Cores DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Indicativo", + "dstar_rpt2" => "RPT2 Indicativo", + "dstar_irc_password" => "Senha ircDDBGateway", + "dstar_default_ref" => "Refletor Principal", + "aprs_host" => "Servidor APRS", + "dstar_irc_lang" => "Idioma ircDDBGateway", + "dstar_irc_time" => "Anúncio a cada Hora", + // Config Page - YSF Configuration + "ysf_startup_host" => "Servidor Inicial YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Servidor Inicial P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Servidor Inicial NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Acesso ao Painel", + "fw_irc" => "Remoto ircDDBGateway", + "fw_ssh" => "Acesso via SSH", + // Config Page - Password + "user" => "Nome do Usuário", + "password" => "Senha", + "set_password" => "Modificar Senha", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Habilitar Modos", + "net_status" => "Status de Rede", + "internet" => "Internet", + "radio_info" => "Info do Rádio", + "dstar_repeater" => "Repetidora D-Star", + "dstar_net" => "Rede D-Star", + "dmr_repeater" => "Repetidora DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "Rede YSF", + "p25_radio" => "Rádio P25", + "p25_net" => "Rede P25", + "nxdn_radio" => "Rádio NDXN", + "nxdn_net" => "Rede NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Hora", + "mode" => "Modo", + "callsign" => "Indicativo", + "target" => "Alvo", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Grupo", + "logoff" => "Sair", + "info" => "Informação", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Últimas 20 chamadas via Gateway", + "local_tx_list" => "Últimas 20 chamadas por este Gateway", + "active_starnet_groups" => "Grupo Ativos na Starnet", + "active_starnet_members" => "Grupo de Membros Ativos na Starnet", + "d-star_link_manager" => "Gerenciar Conexão D-Star", + "d-star_link_status" => "Informações do Link D-Star", + "service_status" => "Status do Sistema" ); +?> diff --git a/lang/portuguese_pt.php b/lang/portuguese_pt.php index 2bd52a9..15c1046 100644 --- a/lang/portuguese_pt.php +++ b/lang/portuguese_pt.php @@ -5,152 +5,154 @@ // Updated: 08-Feb-2018 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voz", - "configuration" => "Configuração", - "dashboard_for" => "Painel de Controle de", - // Banner links - "dashboard" => "Painel", - "admin" => "Admin", - "power" => "Ação", - "update" => "Atualizar", - "backup_restore" => "Backup/Restauro", - "factory_reset" => "Reset", - "live_logs" => "Logs online", - // Config page section headdings - "hardware_info" => "Informações Hardware do Gateway", - "control_software" => "Controle Software", - "mmdvmhost_config" => "MMDVMHost Configuração", - "general_config" => "Configurações Gerais", - "dmr_config" => "Configuração do DMR", - "dstar_config" => "Configuração do DSTAR", - "ysf_config" => "Configuração do Yaesu System Fusion", - "p25_config" => "Configuração do P25", - "nxdn_config" => "Configuração do NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "Configuração do POCSAG", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Configuração do Wireless", - "fw_config" => "Configuração do Firewall", - "remote_access_pw" => "Senha do Acesso Remoto", - // Config Page - Section General - "setting" => "Configurações", - "value" => "Valores", - "apply" => "Aplicar", - // Config Page - Gateway Hardware Information - "hostname" => "Nome do Host", - "kernel" => "Kernel", - "platform" => "Plataforma", - "cpu_load" => "Carga do CPU", - "cpu_temp" => "Temperatura do CPU", - // Config Page - Control Software - "controller_software" => "Tipo de Software", - "controller_mode" => "Modo de Controle", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Modo DMR", - "d-star_mode" => "Modo DSTAR", - "ysf_mode" => "Modo YSF", - "p25_mode" => "Modo P25", - "nxdn_mode" => "Modo NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "Exibição MMDVM", - "mode_hangtime" => "Espera tempo do Modo", - // Config Page - General Configuration - "node_call" => "Indicativo do Nó", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Frequência do Rádio", - "lattitude" => "Latitude", - "longitude" => "Longitude", - "town" => "Cidade", - "country" => "País", - "url" => "URL", - "radio_type" => "Tipo de Radio/Modem", - "node_type" => "Tipo de Nó", - "timezone" => "Horário do Sistema", - "dash_lang" => "Idioma do Painel de Controle", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "Rede BrandMeister", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "Rede DMR+", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Enable", - "dmr_cc" => "Código de Cores DMR", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "R1 Indicativo", - "dstar_rpt2" => "R2 Indicativo", - "dstar_irc_password" => "Senha ircDDBGateway", - "dstar_default_ref" => "Refletor Principal", - "aprs_host" => "Servidor APRS", - "dstar_irc_lang" => "Idioma ircDDBGateway", - "dstar_irc_time" => "Anúncio a cada hora", - // Config Page - YSF Configuration - "ysf_startup_host" => "Servidor Inicial YSF", - // Config Page - P25 Configuration - "p25_startup_host" => "Servidor Inicial P25", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "Servidor Inicial NXDN", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Acesso ao Painel", - "fw_irc" => "Remoto ircDDBGateway", - "fw_ssh" => "Acesso via SSH", - // Config Page - Password - "user" => "Nome utilizador", - "password" => "Senha", - "set_password" => "Modificar Senha", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Habilitar Modos", - "net_status" => "Estado da Rede", - "internet" => "Internet", - "radio_info" => "Info do Rádio", - "dstar_repeater" => "Repetidor DSTAR", - "dstar_net" => "Rede DSTAR", - "dmr_repeater" => "Repetidor DMR", - "dmr_master" => "DMR Master", - "ysf_net" => "Rede YSF", - "p25_radio" => "Rádio P25", - "p25_net" => "Rede P25", - "nxdn_radio" => "Rádio NXDN", - "nxdn_net" => "Rede NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Hora", - "mode" => "Modo", - "callsign" => "Indicativo", // versão traduzida de "callsign" - "target" => "Alvo", // versão traduzida de "Target" - "src" => "Origem", // versão traduzida de "Source" - "dur" => "Dur.", // versão abreviada de "Duration" - "loss" => "Perda", - "ber" => "BER", // versão abreviada de "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Grupo", - "logoff" => "Sair", - "info" => "Informação", - "utot" => "UTOT", // abreviatura para Timeout do utilizador - "gtot" => "GTOT", // abreviatura para Timeout do grupo - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Últimas 20 chamadas através deste Gateway", - "local_tx_list" => "Últimas 20 chamadas deste Gateway", - "active_starnet_groups" => "Grupos ativos na Starnet", - "active_starnet_members" => "Grupo de membros ativos na Starnet", - "d-star_link_manager" => "Gerir a ligação DSTAR", - "d-star_link_status" => "Informações do Link DSTAR", - "service_status" => "Estado do Sistema" + // Banner texts + "digital_voice" => "Digital Voz", + "configuration" => "Configuração", + "dashboard_for" => "Painel de Controle de", + // Banner links + "dashboard" => "Painel", + "admin" => "Admin", + "power" => "Ação", + "update" => "Atualizar", + "backup_restore" => "Backup/Restauro", + "factory_reset" => "Reset", + "live_logs" => "Logs online", + // Config page section headdings + "hardware_info" => "Informações Hardware do Gateway", + "control_software" => "Controle Software", + "mmdvmhost_config" => "MMDVMHost Configuração", + "general_config" => "Configurações Gerais", + "dmr_config" => "Configuração do DMR", + "dstar_config" => "Configuração do DSTAR", + "ysf_config" => "Configuração do Yaesu System Fusion", + "p25_config" => "Configuração do P25", + "nxdn_config" => "Configuração do NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuração do POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuração do Wireless", + "fw_config" => "Configuração do Firewall", + "remote_access_pw" => "Senha do Acesso Remoto", + // Config Page - Section General + "setting" => "Configurações", + "value" => "Valores", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Nome do Host", + "kernel" => "Kernel", + "platform" => "Plataforma", + "cpu_load" => "Carga do CPU", + "cpu_temp" => "Temperatura do CPU", + // Config Page - Control Software + "controller_software" => "Tipo de Software", + "controller_mode" => "Modo de Controle", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Modo DMR", + "d-star_mode" => "Modo DSTAR", + "ysf_mode" => "Modo YSF", + "p25_mode" => "Modo P25", + "nxdn_mode" => "Modo NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Exibição MMDVM", + "mode_hangtime" => "Espera tempo do Modo", + // Config Page - General Configuration + "node_call" => "Indicativo do Nó", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frequência do Rádio", + "lattitude" => "Latitude", + "longitude" => "Longitude", + "town" => "Cidade", + "country" => "País", + "url" => "URL", + "radio_type" => "Tipo de Radio/Modem", + "node_type" => "Tipo de Nó", + "timezone" => "Horário do Sistema", + "dash_lang" => "Idioma do Painel de Controle", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "Rede BrandMeister", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "Rede DMR+", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "Código de Cores DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "R1 Indicativo", + "dstar_rpt2" => "R2 Indicativo", + "dstar_irc_password" => "Senha ircDDBGateway", + "dstar_default_ref" => "Refletor Principal", + "aprs_host" => "Servidor APRS", + "dstar_irc_lang" => "Idioma ircDDBGateway", + "dstar_irc_time" => "Anúncio a cada hora", + // Config Page - YSF Configuration + "ysf_startup_host" => "Servidor Inicial YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Servidor Inicial P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Servidor Inicial NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Acesso ao Painel", + "fw_irc" => "Remoto ircDDBGateway", + "fw_ssh" => "Acesso via SSH", + // Config Page - Password + "user" => "Nome utilizador", + "password" => "Senha", + "set_password" => "Modificar Senha", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Habilitar Modos", + "net_status" => "Estado da Rede", + "internet" => "Internet", + "radio_info" => "Info do Rádio", + "dstar_repeater" => "Repetidor DSTAR", + "dstar_net" => "Rede DSTAR", + "dmr_repeater" => "Repetidor DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "Rede YSF", + "p25_radio" => "Rádio P25", + "p25_net" => "Rede P25", + "nxdn_radio" => "Rádio NXDN", + "nxdn_net" => "Rede NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Hora", + "mode" => "Modo", + "callsign" => "Indicativo", // versão traduzida de "callsign" + "target" => "Alvo", // versão traduzida de "Target" + "src" => "Origem", // versão traduzida de "Source" + "dur" => "Dur.", // versão abreviada de "Duration" + "loss" => "Perda", + "ber" => "BER", // versão abreviada de "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Grupo", + "logoff" => "Sair", + "info" => "Informação", + "utot" => "UTOT", // abreviatura para Timeout do utilizador + "gtot" => "GTOT", // abreviatura para Timeout do grupo + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Últimas 20 chamadas através deste Gateway", + "local_tx_list" => "Últimas 20 chamadas deste Gateway", + "active_starnet_groups" => "Grupos ativos na Starnet", + "active_starnet_members" => "Grupo de membros ativos na Starnet", + "d-star_link_manager" => "Gerir a ligação DSTAR", + "d-star_link_status" => "Informações do Link DSTAR", + "service_status" => "Estado do Sistema" ); +?> + diff --git a/lang/romanian_ro.php b/lang/romanian_ro.php index 0d80b45..8af9f0a 100644 --- a/lang/romanian_ro.php +++ b/lang/romanian_ro.php @@ -5,152 +5,153 @@ // Updated: 12-Jun-2020 // $lang = array ( - // Banner texts - "digital_voice" => "Voce Digitala", - "configuration" => "Configuratii", - "dashboard_for" => "Panou Control pentru", - // Banner links - "dashboard" => "Panou Control", - "admin" => "Administrator", - "power" => "Alimentare", - "update" => "Actualizare", - "backup_restore" => "Copie Rezerva/Restabilire", - "factory_reset" => "Resetare Stare Initiala", - "live_logs" => "Jurnal Live", - // Config page section headdings - "hardware_info" => "Informatii Hardware Gateway", - "control_software" => "Control Software", - "mmdvmhost_config" => "Configurare MMDVMHost", - "general_config" => "Configurari Generale", - "dmr_config" => "Configurari DMR", - "dstar_config" => "Configurari D-Star", - "ysf_config" => "Configurari Yaesu System Fusion", - "p25_config" => "Configurari P25", - "nxdn_config" => "Configurari NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "Configurari POCSAG", - "mobilegps_config" => "Configurari Mobile GPS", - "wifi_config" => "Configurari Retea Wireless", - "fw_config" => "Configurari Firewall", - "remote_access_pw" => "Parola Acces Exterior", - // Config Page - Section General - "setting" => "Setari", - "value" => "Valoare", - "apply" => "Salvare Setari", - // Config Page - Gateway Hardware Information - "hostname" => "Denumire Detinator", - "kernel" => "Nucleu", - "platform" => "Platforma", - "cpu_load" => "Incarcare CPU", - "cpu_temp" => "Temeratura CPU", - // Config Page - Control Software - "controller_software" => "Program de Control", - "controller_mode" => "Mod Control", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Mod DMR", - "d-star_mode" => "Mod D-Star", - "ysf_mode" => "Mod YSF", - "p25_mode" => "Mod P25", - "nxdn_mode" => "Mod NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "Tip Display MMDVM", - "mode_hangtime" => "Control Hangtime", - // Config Page - General Configuration - "node_call" => "Indicativ Node", - "dmr_id" => "CCS7/ID DMR", - "radio_freq" => "Frecventa Radio", - "lattitude" => "Latitudine", - "longitude" => "Longitudine", - "town" => "Oras", - "country" => "Tara", - "url" => "URL", - "radio_type" => "Model Radio/Modem", - "node_type" => "Model Node", - "timezone" => "Time Zone Sistem", - "dash_lang" => "Limba Panou Control", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "Reteaua BrandMeister", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "Retea DMR+", - "xlx_master" => "XLX Master", - "xlx_enable" => "Activare XLX Master", - "dmr_cc" => "Cod Culoare DMR", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "Indicativ RPT1", - "dstar_rpt2" => "Indicativ RPT2", - "dstar_irc_password" => "parola ircDDBGateway", - "dstar_default_ref" => "Reflector Implicit ", - "aprs_host" => "Detinator APRS", - "dstar_irc_lang" => "Limba ircDDBGateway", - "dstar_irc_time" => "Timp instiintare", - // Config Page - YSF Configuration - "ysf_startup_host" => "lansare Detinator YSF", - // Config Page - P25 Configuration - "p25_startup_host" => "lansare Detinator P25", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "lansare Detinator NXDN", - "nxdn_ran" => "Lansare NXDN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "Activare Mobile GPS", - "mobilegps_port" => "Port GPS", - "mobilegps_speed" => "Viteza Port GPS", - // Config Page - Firewall Configuration - "fw_dash" => "Acces Panou Control", - "fw_irc" => "Control Exterior ircDDBGateway", - "fw_ssh" => "Acces SSH", - // Config Page - Password - "user" => "Nume Utilizator", - "password" => "Parola", - "set_password" => "Setare Parola", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Moduri Activate ", - "net_status" => "Stare Retea", - "internet" => "Internet", - "radio_info" => "Info Radio", - "dstar_repeater" => "Repetor D-Star", - "dstar_net" => "Reteaua D-Star", - "dmr_repeater" => "Repetor DMR", - "dmr_master" => "DMR Master", - "ysf_net" => "Reteaua YSF", - "p25_radio" => "P25 Radio", - "p25_net" => "Reteaua P25", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "Reteaua NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Ora", - "mode" => "Mod", - "callsign" => "Indicativ", - "target" => "Apel Catre", - "src" => "Src", // Prescurtare "Sursa" - "dur" => "Dur", // prescurtare "Durata" - "loss" => "Pierderi", - "ber" => "BER", // Prescurtare "Rata Eroare Biti" - // POCSAG Specific - "pocsag_list" => "Activitate Gateway DAPNET", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Mesaj", - // Dashboard - Extra Info - "group" => "Grup", - "logoff" => "Deconectare", - "info" => "Informatii", - "utot" => "UTOT", // Prescurtare User Timeout - "gtot" => "GTOT", // Prescurtare Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Ultimele 20 Apeluri Receptionate prin acest Gateway", - "local_tx_list" => "Ultimele 20 Apeluri care au accesat acest Gateway", - "active_starnet_groups" => "Grupuri Active Starnet", - "active_starnet_members" => "Membrii activi in Grupuri Starnet ", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "Informatii Legatura D-Star", - "service_status" => "Stare Serviciu" + // Banner texts + "digital_voice" => "Voce Digitala", + "configuration" => "Configuratii", + "dashboard_for" => "Panou Control pentru", + // Banner links + "dashboard" => "Panou Control", + "admin" => "Administrator", + "power" => "Alimentare", + "update" => "Actualizare", + "backup_restore" => "Copie Rezerva/Restabilire", + "factory_reset" => "Resetare Stare Initiala", + "live_logs" => "Jurnal Live", + // Config page section headdings + "hardware_info" => "Informatii Hardware Gateway", + "control_software" => "Control Software", + "mmdvmhost_config" => "Configurare MMDVMHost", + "general_config" => "Configurari Generale", + "dmr_config" => "Configurari DMR", + "dstar_config" => "Configurari D-Star", + "ysf_config" => "Configurari Yaesu System Fusion", + "p25_config" => "Configurari P25", + "nxdn_config" => "Configurari NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configurari POCSAG", + "mobilegps_config" => "Configurari Mobile GPS", + "wifi_config" => "Configurari Retea Wireless", + "fw_config" => "Configurari Firewall", + "remote_access_pw" => "Parola Acces Exterior", + // Config Page - Section General + "setting" => "Setari", + "value" => "Valoare", + "apply" => "Salvare Setari", + // Config Page - Gateway Hardware Information + "hostname" => "Denumire Detinator", + "kernel" => "Nucleu", + "platform" => "Platforma", + "cpu_load" => "Incarcare CPU", + "cpu_temp" => "Temeratura CPU", + // Config Page - Control Software + "controller_software" => "Program de Control", + "controller_mode" => "Mod Control", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Mod DMR", + "d-star_mode" => "Mod D-Star", + "ysf_mode" => "Mod YSF", + "p25_mode" => "Mod P25", + "nxdn_mode" => "Mod NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Tip Display MMDVM", + "mode_hangtime" => "Control Hangtime", + // Config Page - General Configuration + "node_call" => "Indicativ Node", + "dmr_id" => "CCS7/ID DMR", + "radio_freq" => "Frecventa Radio", + "lattitude" => "Latitudine", + "longitude" => "Longitudine", + "town" => "Oras", + "country" => "Tara", + "url" => "URL", + "radio_type" => "Model Radio/Modem", + "node_type" => "Model Node", + "timezone" => "Time Zone Sistem", + "dash_lang" => "Limba Panou Control", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "Reteaua BrandMeister", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "Retea DMR+", + "xlx_master" => "XLX Master", + "xlx_enable" => "Activare XLX Master", + "dmr_cc" => "Cod Culoare DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Indicativ RPT1", + "dstar_rpt2" => "Indicativ RPT2", + "dstar_irc_password" => "parola ircDDBGateway", + "dstar_default_ref" => "Reflector Implicit ", + "aprs_host" => "Detinator APRS", + "dstar_irc_lang" => "Limba ircDDBGateway", + "dstar_irc_time" => "Timp instiintare", + // Config Page - YSF Configuration + "ysf_startup_host" => "lansare Detinator YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "lansare Detinator P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "lansare Detinator NXDN", + "nxdn_ran" => "Lansare NXDN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "Activare Mobile GPS", + "mobilegps_port" => "Port GPS", + "mobilegps_speed" => "Viteza Port GPS", + // Config Page - Firewall Configuration + "fw_dash" => "Acces Panou Control", + "fw_irc" => "Control Exterior ircDDBGateway", + "fw_ssh" => "Acces SSH", + // Config Page - Password + "user" => "Nume Utilizator", + "password" => "Parola", + "set_password" => "Setare Parola", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Moduri Activate ", + "net_status" => "Stare Retea", + "internet" => "Internet", + "radio_info" => "Info Radio", + "dstar_repeater" => "Repetor D-Star", + "dstar_net" => "Reteaua D-Star", + "dmr_repeater" => "Repetor DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "Reteaua YSF", + "p25_radio" => "P25 Radio", + "p25_net" => "Reteaua P25", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "Reteaua NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Ora", + "mode" => "Mod", + "callsign" => "Indicativ", + "target" => "Apel Catre", + "src" => "Src", // Prescurtare "Sursa" + "dur" => "Dur", // prescurtare "Durata" + "loss" => "Pierderi", + "ber" => "BER", // Prescurtare "Rata Eroare Biti" + // POCSAG Specific + "pocsag_list" => "Activitate Gateway DAPNET", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Mesaj", + // Dashboard - Extra Info + "group" => "Grup", + "logoff" => "Deconectare", + "info" => "Informatii", + "utot" => "UTOT", // Prescurtare User Timeout + "gtot" => "GTOT", // Prescurtare Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Ultimele 20 Apeluri Receptionate prin acest Gateway", + "local_tx_list" => "Ultimele 20 Apeluri care au accesat acest Gateway", + "active_starnet_groups" => "Grupuri Active Starnet", + "active_starnet_members" => "Membrii activi in Grupuri Starnet ", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "Informatii Legatura D-Star", + "service_status" => "Stare Serviciu" ); +?> diff --git a/lang/slovenian_sl.php b/lang/slovenian_sl.php index 72f76a3..0f0b44b 100644 --- a/lang/slovenian_sl.php +++ b/lang/slovenian_sl.php @@ -5,152 +5,153 @@ // Updated: 20-Jun-2019 // $lang = array ( - // Banner texts - "digital_voice" => "DV", - "configuration" => "Nastavitve", - "dashboard_for" => "Nadzorna plošča", - // Banner links - "dashboard" => "Nadzorna plošča", - "admin" => "Skrbniški način", - "power" => "Vklop/Izklop", - "update" => "Posodobitev", - "backup_restore" => "Varnostno kopiranje", - "factory_reset" => "Tovarniške nastavitve", - "live_logs" => "Dnevnik", - // Config page section headdings - "hardware_info" => "Informacije o strojni opremi prehoda", - "control_software" => "Nadzorna programska oprema", - "mmdvmhost_config" => "Nastavitve MMDVMHost", - "general_config" => "Splošne nastavitve", - "dmr_config" => "Nastavitve DMR", - "dstar_config" => "Nastavitve D-Star", - "ysf_config" => "Nastavitve Yaesu System Fusion", - "p25_config" => "Nastavitve P25", - "nxdn_config" => "Nastavitve NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "Nastavitve POCSAG", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Nastavitve brezžičnega omrežja", - "fw_config" => "Nastavitve požarnega zidu", - "remote_access_pw" => "Geslo za oddaljeni dostop", - // Config Page - Section General - "setting" => "Nastavitev", - "value" => "Vrednost", - "apply" => "Potrdi spremembe", - // Config Page - Gateway Hardware Information - "hostname" => "Ime gostitelja", - "kernel" => "Jedro", - "platform" => "Platforma", - "cpu_load" => "Obremenitev proc.", - "cpu_temp" => "Temperatura proc.", - // Config Page - Control Software - "controller_software" => "Programska oprema krmilnika", - "controller_mode" => "Način krmilnika", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Način DMR", - "d-star_mode" => "Način D-Star", - "ysf_mode" => "Način YSF", - "p25_mode" => "Način P25", - "nxdn_mode" => "Način NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "Tip MMDVM zaslona", - "mode_hangtime" => "Obstanek načina", - // Config Page - General Configuration - "node_call" => "Klicni znak vozlišča", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Frekvenca", - "lattitude" => "Zemljepisna širina", - "longitude" => "Zemljepisna dolžina", - "town" => "Kraj", - "country" => "Država", - "url" => "URL", - "radio_type" => "Vrsta sprejemnika/modema", - "node_type" => "Vrsta vozlišča", - "timezone" => "Časovni pas", - "dash_lang" => "Jezik nadzorne plošče", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister omrežje", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ omrežje", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Enable", - "dmr_cc" => "DMR Barvna Koda (CC)", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "Klicni znak RPT1", - "dstar_rpt2" => "Klicni znak RPT2", - "dstar_irc_password" => "Geslo za oddaljeni dostop", - "dstar_default_ref" => "Privzeti reflektor", - "aprs_host" => "Gostitelj APRS", - "dstar_irc_lang" => "Jezik ircDDBGateway", - "dstar_irc_time" => "Napoved časa", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF zagonski gostitelj", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 zagonski gostitelj", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN zagonski gostitelj", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Dostop do nadzorne plošče", - "fw_irc" => "Dostop ircDDBGateway", - "fw_ssh" => "Dostop SSH", - // Config Page - Password - "user" => "Uporabniški ime", - "password" => "Geslo", - "set_password" => "Nastavi geslo", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Omogočeni načini", - "net_status" => "Stanje omrežja", - "internet" => "Internet", - "radio_info" => "Info o sprejemniku", - "dstar_repeater" => "Repetitor D-Star", - "dstar_net" => "D-Star Omrežje", - "dmr_repeater" => "Repetitor DMR", - "dmr_master" => "Master DMR", - "ysf_net" => "Omrežje YSF", - "p25_radio" => "Radio P25", - "p25_net" => "Omrežje P25", - "nxdn_radio" => "Radio NXDN", - "nxdn_net" => "Omrežje NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Čas", - "mode" => "Način", - "callsign" => "Klicni znak", - "target" => "Cilj", - "src" => "Vir", // Short version of "Source" - "dur" => "Dol", // Short version of "Duration" - "loss" => "Izguba", - "ber" => "DNB", // Short version of "Bit Error Rate" - delež napačnih bitov - // POCSAG Specific - "pocsag_list" => "Aktivnost DAPNET prehoda", - "pocsag_timeslot" => "Časovno okno (TS)", - "pocsag_msg" => "Sporočilo", - // Dashboard - Extra Info - "group" => "Skupina", - "logoff" => "Odjava", - "info" => "Informacija", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Aktivnost prehoda", - "local_tx_list" => "Lokalna RF aktivnost", - "active_starnet_groups" => "Aktivne skupine Starnet", - "active_starnet_members" => "Aktivni uporabniki Starnet", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "D-Star Link Informacije", - "service_status" => "Stanje storitev" + // Banner texts + "digital_voice" => "DV", + "configuration" => "Nastavitve", + "dashboard_for" => "Nadzorna plošča", + // Banner links + "dashboard" => "Nadzorna plošča", + "admin" => "Skrbniški način", + "power" => "Vklop/Izklop", + "update" => "Posodobitev", + "backup_restore" => "Varnostno kopiranje", + "factory_reset" => "Tovarniške nastavitve", + "live_logs" => "Dnevnik", + // Config page section headdings + "hardware_info" => "Informacije o strojni opremi prehoda", + "control_software" => "Nadzorna programska oprema", + "mmdvmhost_config" => "Nastavitve MMDVMHost", + "general_config" => "Splošne nastavitve", + "dmr_config" => "Nastavitve DMR", + "dstar_config" => "Nastavitve D-Star", + "ysf_config" => "Nastavitve Yaesu System Fusion", + "p25_config" => "Nastavitve P25", + "nxdn_config" => "Nastavitve NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Nastavitve POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Nastavitve brezžičnega omrežja", + "fw_config" => "Nastavitve požarnega zidu", + "remote_access_pw" => "Geslo za oddaljeni dostop", + // Config Page - Section General + "setting" => "Nastavitev", + "value" => "Vrednost", + "apply" => "Potrdi spremembe", + // Config Page - Gateway Hardware Information + "hostname" => "Ime gostitelja", + "kernel" => "Jedro", + "platform" => "Platforma", + "cpu_load" => "Obremenitev proc.", + "cpu_temp" => "Temperatura proc.", + // Config Page - Control Software + "controller_software" => "Programska oprema krmilnika", + "controller_mode" => "Način krmilnika", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Način DMR", + "d-star_mode" => "Način D-Star", + "ysf_mode" => "Način YSF", + "p25_mode" => "Način P25", + "nxdn_mode" => "Način NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "Tip MMDVM zaslona", + "mode_hangtime" => "Obstanek načina", + // Config Page - General Configuration + "node_call" => "Klicni znak vozlišča", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frekvenca", + "lattitude" => "Zemljepisna širina", + "longitude" => "Zemljepisna dolžina", + "town" => "Kraj", + "country" => "Država", + "url" => "URL", + "radio_type" => "Vrsta sprejemnika/modema", + "node_type" => "Vrsta vozlišča", + "timezone" => "Časovni pas", + "dash_lang" => "Jezik nadzorne plošče", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister omrežje", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ omrežje", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Barvna Koda (CC)", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "Klicni znak RPT1", + "dstar_rpt2" => "Klicni znak RPT2", + "dstar_irc_password" => "Geslo za oddaljeni dostop", + "dstar_default_ref" => "Privzeti reflektor", + "aprs_host" => "Gostitelj APRS", + "dstar_irc_lang" => "Jezik ircDDBGateway", + "dstar_irc_time" => "Napoved časa", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF zagonski gostitelj", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 zagonski gostitelj", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN zagonski gostitelj", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Dostop do nadzorne plošče", + "fw_irc" => "Dostop ircDDBGateway", + "fw_ssh" => "Dostop SSH", + // Config Page - Password + "user" => "Uporabniški ime", + "password" => "Geslo", + "set_password" => "Nastavi geslo", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Omogočeni načini", + "net_status" => "Stanje omrežja", + "internet" => "Internet", + "radio_info" => "Info o sprejemniku", + "dstar_repeater" => "Repetitor D-Star", + "dstar_net" => "D-Star Omrežje", + "dmr_repeater" => "Repetitor DMR", + "dmr_master" => "Master DMR", + "ysf_net" => "Omrežje YSF", + "p25_radio" => "Radio P25", + "p25_net" => "Omrežje P25", + "nxdn_radio" => "Radio NXDN", + "nxdn_net" => "Omrežje NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Čas", + "mode" => "Način", + "callsign" => "Klicni znak", + "target" => "Cilj", + "src" => "Vir", // Short version of "Source" + "dur" => "Dol", // Short version of "Duration" + "loss" => "Izguba", + "ber" => "DNB", // Short version of "Bit Error Rate" - delež napačnih bitov + // POCSAG Specific + "pocsag_list" => "Aktivnost DAPNET prehoda", + "pocsag_timeslot" => "Časovno okno (TS)", + "pocsag_msg" => "Sporočilo", + // Dashboard - Extra Info + "group" => "Skupina", + "logoff" => "Odjava", + "info" => "Informacija", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Aktivnost prehoda", + "local_tx_list" => "Lokalna RF aktivnost", + "active_starnet_groups" => "Aktivne skupine Starnet", + "active_starnet_members" => "Aktivni uporabniki Starnet", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Informacije", + "service_status" => "Stanje storitev" ); +?> diff --git a/lang/spanish_es.php b/lang/spanish_es.php index 4b4833c..0afd0a5 100644 --- a/lang/spanish_es.php +++ b/lang/spanish_es.php @@ -5,152 +5,153 @@ // 27-Sept-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Voz Digital", - "configuration" => "Configuracion", - "dashboard_for" => "Panel de control de", - // Banner links - "dashboard" => "Panel de Control", - "admin" => "Administrar", - "power" => "Reiniciar/Apagar", - "update" => "Actualizar", - "backup_restore" => "Backup/Restaurar copia de seguridad", - "factory_reset" => "Restaurar datos de fabrica", - "live_logs" => "Informes-Logs", - // Config page section headdings - "hardware_info" => "Informacion de hardware", - "control_software" => "Control de software", - "mmdvmhost_config" => "Configuracion de MMDVMHost", - "general_config" => "Configuracion General", - "dmr_config" => "Configuracion de DMR", - "dstar_config" => "Configuracion de DSTAR", - "ysf_config" => "Configuracion de Yaesu C4FM fusion", - "p25_config" => "Configuracion de P25", - "nxdn_config" => "Configuracion de NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "Configuracion de POCSAG", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Configuracion WIFI", - "fw_config" => "Configuracion del cortafuegos", - "remote_access_pw" => "Contraseña accceso Remoto", - // Config Page - Section General - "setting" => "Ajustes", - "value" => "Valor", - "apply" => "Aplicar", - // Config Page - Gateway Hardware Information - "hostname" => "Hostname", - "kernel" => "Kernel", - "platform" => "Plataforma", - "cpu_load" => "Carga de la CPU", - "cpu_temp" => "Temperatura CPU", - // Config Page - Control Software - "controller_software" => "Controlador Software", - "controller_mode" => "Controlador de Modo", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "Modo DMR", - "d-star_mode" => "Modo D-Star", - "ysf_mode" => "Modo YSF", - "p25_mode" => "Modo P25", - "nxdn_mode" => "Modo NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Tipo Display", - "mode_hangtime" => "Modo tiempo de suspension", - // Config Page - General Configuration - "node_call" => "Nodo indicativo de llamada", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Frecuencia RX/TX", - "lattitude" => "Latitud", - "longitude" => "Longitud", - "town" => "Ciudad", - "country" => "Pais", - "url" => "URL", - "radio_type" => "Radio/Tipo modem", - "node_type" => "Nodo Tipo", - "timezone" => "Zona horaria", - "dash_lang" => "Idioma del Panel de Control", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "Master de BrandMeister", - "bm_network" => "Red de BrandMeister", - "dmr_plus_master" => "Master de DMR+", - "dmr_plus_network" => "Red de DMR+", - "xlx_master" => "Master de XLX", - "xlx_enable" => "Habilitar Master XLX", - "dmr_cc" => "Codigo de color de DMR", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 indicativo de llamada", - "dstar_rpt2" => "RPT2 indicativo de llamada", - "dstar_irc_password" => "contrasena de ircDDBGateway", - "dstar_default_ref" => "Reflector predeterminado", - "aprs_host" => "Servidor de APRS", - "dstar_irc_lang" => "Idioma de ircDDBGateway", - "dstar_irc_time" => "Intervalo de Balizas", - // Config Page - YSF Configuration - "ysf_startup_host" => "Servidor de Inicio YSF", - // Config Page - P25 Configuration - "p25_startup_host" => "Servidor de Inicio P25", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "Servidor de Inicio NXDN", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Tablero de acceso", - "fw_irc" => "ircDDBGateway Remoto", - "fw_ssh" => "Acceso por SSH", - // Config Page - Password - "user" => "Nombre de usuario", - "password" => "Contrasena", - "set_password" => "Establecer contrasena", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Modos habilitados", - "net_status" => "Estado de la red", - "internet" => "Internet", - "radio_info" => "Informacion de Radio", - "dstar_repeater" => "Repetidor de D-Star", - "dstar_net" => "Red de D-Star", - "dmr_repeater" => "Repetidor de DMR", - "dmr_master" => "Master de DMR", - "ysf_net" => "Red de YSF", - "p25_radio" => "Radio de P25", - "p25_net" => "Red de P25", - "nxdn_radio" => "Radio de NXDN", - "nxdn_net" => "Red de NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Hora", - "mode" => "Modo", - "callsign" => "Indicativo de llamada", - "target" => "Destino", - "src" => "SRC", //version corta de "fuente" - "dur" => "DUR", //version corta de "duracion" - "loss" => "Perdida", - "ber" => "BER", //version corta de "Error de bit" - // POCSAG Specific - "pocsag_list" => "Actividad de DAPNET Gateway", - "pocsag_timeslot" => "Slot de Tiempo", - "pocsag_msg" => "Mensaje", - // Dashboard - Extra Info - "group" => "Grupos", - "logoff" => "Finalizar", - "info" => "Informacion", - "utot" => "UTOT", //tiempo agotado para usuario - "gtot" => "GTOT", // tiempo agotado para grupo - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Ultimas 20 llamadas que accedieron al sistema", - "local_tx_list" => "Ultimas 20 llamadas que accedieron a ese puerto", - "active_starnet_groups" => "Grupos activos Starnet", - "active_starnet_members" => "Miembros activos del grupo Starnet", - "d-star_link_manager" => "Gestor de enlaces D-Star", - "d-star_link_status" => "Informacion de enlaces D-Star", - "service_status" => "Estado del servicio" + // Banner texts + "digital_voice" => "Voz Digital", + "configuration" => "Configuracion", + "dashboard_for" => "Panel de control de", + // Banner links + "dashboard" => "Panel de Control", + "admin" => "Administrar", + "power" => "Reiniciar/Apagar", + "update" => "Actualizar", + "backup_restore" => "Backup/Restaurar copia de seguridad", + "factory_reset" => "Restaurar datos de fabrica", + "live_logs" => "Informes-Logs", + // Config page section headdings + "hardware_info" => "Informacion de hardware", + "control_software" => "Control de software", + "mmdvmhost_config" => "Configuracion de MMDVMHost", + "general_config" => "Configuracion General", + "dmr_config" => "Configuracion de DMR", + "dstar_config" => "Configuracion de DSTAR", + "ysf_config" => "Configuracion de Yaesu C4FM fusion", + "p25_config" => "Configuracion de P25", + "nxdn_config" => "Configuracion de NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "Configuracion de POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuracion WIFI", + "fw_config" => "Configuracion del cortafuegos", + "remote_access_pw" => "Contraseña accceso Remoto", + // Config Page - Section General + "setting" => "Ajustes", + "value" => "Valor", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Plataforma", + "cpu_load" => "Carga de la CPU", + "cpu_temp" => "Temperatura CPU", + // Config Page - Control Software + "controller_software" => "Controlador Software", + "controller_mode" => "Controlador de Modo", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "Modo DMR", + "d-star_mode" => "Modo D-Star", + "ysf_mode" => "Modo YSF", + "p25_mode" => "Modo P25", + "nxdn_mode" => "Modo NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Tipo Display", + "mode_hangtime" => "Modo tiempo de suspension", + // Config Page - General Configuration + "node_call" => "Nodo indicativo de llamada", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Frecuencia RX/TX", + "lattitude" => "Latitud", + "longitude" => "Longitud", + "town" => "Ciudad", + "country" => "Pais", + "url" => "URL", + "radio_type" => "Radio/Tipo modem", + "node_type" => "Nodo Tipo", + "timezone" => "Zona horaria", + "dash_lang" => "Idioma del Panel de Control", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "Master de BrandMeister", + "bm_network" => "Red de BrandMeister", + "dmr_plus_master" => "Master de DMR+", + "dmr_plus_network" => "Red de DMR+", + "xlx_master" => "Master de XLX", + "xlx_enable" => "Habilitar Master XLX", + "dmr_cc" => "Codigo de color de DMR", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 indicativo de llamada", + "dstar_rpt2" => "RPT2 indicativo de llamada", + "dstar_irc_password" => "contrasena de ircDDBGateway", + "dstar_default_ref" => "Reflector predeterminado", + "aprs_host" => "Servidor de APRS", + "dstar_irc_lang" => "Idioma de ircDDBGateway", + "dstar_irc_time" => "Intervalo de Balizas", + // Config Page - YSF Configuration + "ysf_startup_host" => "Servidor de Inicio YSF", + // Config Page - P25 Configuration + "p25_startup_host" => "Servidor de Inicio P25", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "Servidor de Inicio NXDN", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Tablero de acceso", + "fw_irc" => "ircDDBGateway Remoto", + "fw_ssh" => "Acceso por SSH", + // Config Page - Password + "user" => "Nombre de usuario", + "password" => "Contrasena", + "set_password" => "Establecer contrasena", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modos habilitados", + "net_status" => "Estado de la red", + "internet" => "Internet", + "radio_info" => "Informacion de Radio", + "dstar_repeater" => "Repetidor de D-Star", + "dstar_net" => "Red de D-Star", + "dmr_repeater" => "Repetidor de DMR", + "dmr_master" => "Master de DMR", + "ysf_net" => "Red de YSF", + "p25_radio" => "Radio de P25", + "p25_net" => "Red de P25", + "nxdn_radio" => "Radio de NXDN", + "nxdn_net" => "Red de NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Hora", + "mode" => "Modo", + "callsign" => "Indicativo de llamada", + "target" => "Destino", + "src" => "SRC", //version corta de "fuente" + "dur" => "DUR", //version corta de "duracion" + "loss" => "Perdida", + "ber" => "BER", //version corta de "Error de bit" + // POCSAG Specific + "pocsag_list" => "Actividad de DAPNET Gateway", + "pocsag_timeslot" => "Slot de Tiempo", + "pocsag_msg" => "Mensaje", + // Dashboard - Extra Info + "group" => "Grupos", + "logoff" => "Finalizar", + "info" => "Informacion", + "utot" => "UTOT", //tiempo agotado para usuario + "gtot" => "GTOT", // tiempo agotado para grupo + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Ultimas 20 llamadas que accedieron al sistema", + "local_tx_list" => "Ultimas 20 llamadas que accedieron a ese puerto", + "active_starnet_groups" => "Grupos activos Starnet", + "active_starnet_members" => "Miembros activos del grupo Starnet", + "d-star_link_manager" => "Gestor de enlaces D-Star", + "d-star_link_status" => "Informacion de enlaces D-Star", + "service_status" => "Estado del servicio" ); +?> diff --git a/lang/spanish_mx.php b/lang/spanish_mx.php index 411d914..5d2c801 100644 --- a/lang/spanish_mx.php +++ b/lang/spanish_mx.php @@ -5,152 +5,153 @@ // 06-Aug-2017 // $lang = array ( - // Banner texts - "digital_voice" => "Voz Digital", - "configuration" => "Configuracion", - "dashboard_for" => "Tablero para", - // Banner links - "dashboard" => "Tablero", - "admin" => "Admin", - "power" => "Poder", - "update" => "Actualizar", - "backup_restore" => "Copia deseguridad_restaurar", - "factory_reset" => "Restablecimiento de fabrica", - "live_logs" => "Vivo Logs", - // Config page section headdings - "hardware_info" => "Puerta hardware Informacion", - "control_software" => "Control software", - "mmdvmhost_config" => "MMDVMHost Configuracion", - "general_config" => "General Configuracion", - "dmr_config" => "DMR Configuracion", - "dstar_config" => "D-Star Configuracion", - "ysf_config" => "Yaesu Configuracion de sistema fusion", - "p25_config" => "P25 Configuracion", - "nxdn_config" => "NXDN Configuracion", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG Configuracion", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Configuracion Inalambrico", - "fw_config" => "Configuracion firewall", - "remote_access_pw" => "Remoto Accesso contrasena", - // Config Page - Section General - "setting" => "Ajustes", - "value" => "Valor", - "apply" => "Aplicar", - // Config Page - Gateway Hardware Information - "hostname" => "Hostname", - "kernel" => "Kernel", - "platform" => "Plataforma", - "cpu_load" => "CPU Load", - "cpu_temp" => "CPU Temp", - // Config Page - Control Software - "controller_software" => "Controlador Software", - "controller_mode" => "Controlador Modo", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Modo", - "d-star_mode" => "D-Star Modo", - "ysf_mode" => "YSF Modo", - "p25_mode" => "P25 Modo", - "nxdn_mode" => "NXDN Modo", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Tipo de muestra", - "mode_hangtime" => "Modo tiempo de suspension", - // Config Page - General Configuration - "node_call" => "Nodo signo de llamada", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Radio Frecuencia", - "lattitude" => "Latitud", - "longitude" => "Longitud", - "town" => "Ciudad", - "country" => "Pais", - "url" => "URL", - "radio_type" => "Radio/Tipo modem", - "node_type" => "Nodo Tipo", - "timezone" => "Sistema zona horaria", - "dash_lang" => "Tablero de ldiomas", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister red", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ red", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master habilitar", - "dmr_cc" => "DMR Codigo de color", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 signo de llamada", - "dstar_rpt2" => "RPT2 signo de llamada", - "dstar_irc_password" => "ircDDBGateway contrasena", - "dstar_default_ref" => "Reflector predeterminado", - "aprs_host" => "APRS Host", - "dstar_irc_lang" => "ircDDBGateway Language", - "dstar_irc_time" => "Tiempo Anuncios", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF Lanzamiento Host", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 Lanzamiento Host", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN Lanzamiento Host", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Tablero de acceso", - "fw_irc" => "ircDDBGateway Remoto", - "fw_ssh" => "SSH Acceso", - // Config Page - Password - "user" => "Usuario Nombre", - "password" => "Contrasena", - "set_password" => "Set contrasena", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Modos habilitado", - "net_status" => "Estatus de red", - "internet" => "Internet", - "radio_info" => "Radio Informacion", - "dstar_repeater" => "D-Star Repetidor", - "dstar_net" => "D-Star red", - "dmr_repeater" => "DMR Repetidor", - "dmr_master" => "DMR Master", - "ysf_net" => "YSF red", - "p25_radio" => "P25 Radio", - "p25_net" => "P25 red", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDN red", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Time", - "mode" => "Modo", - "callsign" => "signo de llamada", - "target" => "Objetivo", - "src" => "Src", //version corta de "fuente" - "dur" => "Dur", //version corta de "duracion" - "loss" => "Perdida", - "ber" => "BER", //version corta de "Error de bit" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "Grupos", - "logoff" => "Finalizar", - "info" => "Informacion", - "utot" => "UTOT", //tiempo agotado para usuario - "gtot" => "GTOT", // tiempo agotado para grupo - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Ultimos 20 llamadas escuchadas atraves de este puerto", - "local_tx_list" => "Ultimo 20 llamadas que accesaron este puerto", - "active_starnet_groups" => "Activo grupo Starnet Groups", - "active_starnet_members" => "Activo miembros de grupo Starnet", - "d-star_link_manager" => "D-Star gestar de enlaces", - "d-star_link_status" => "D-Star Informacion de enlaces", - "service_status" => "Estado servicio" + // Banner texts + "digital_voice" => "Voz Digital", + "configuration" => "Configuracion", + "dashboard_for" => "Tablero para", + // Banner links + "dashboard" => "Tablero", + "admin" => "Admin", + "power" => "Poder", + "update" => "Actualizar", + "backup_restore" => "Copia deseguridad_restaurar", + "factory_reset" => "Restablecimiento de fabrica", + "live_logs" => "Vivo Logs", + // Config page section headdings + "hardware_info" => "Puerta hardware Informacion", + "control_software" => "Control software", + "mmdvmhost_config" => "MMDVMHost Configuracion", + "general_config" => "General Configuracion", + "dmr_config" => "DMR Configuracion", + "dstar_config" => "D-Star Configuracion", + "ysf_config" => "Yaesu Configuracion de sistema fusion", + "p25_config" => "P25 Configuracion", + "nxdn_config" => "NXDN Configuracion", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Configuracion", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Configuracion Inalambrico", + "fw_config" => "Configuracion firewall", + "remote_access_pw" => "Remoto Accesso contrasena", + // Config Page - Section General + "setting" => "Ajustes", + "value" => "Valor", + "apply" => "Aplicar", + // Config Page - Gateway Hardware Information + "hostname" => "Hostname", + "kernel" => "Kernel", + "platform" => "Plataforma", + "cpu_load" => "CPU Load", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controlador Software", + "controller_mode" => "Controlador Modo", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Modo", + "d-star_mode" => "D-Star Modo", + "ysf_mode" => "YSF Modo", + "p25_mode" => "P25 Modo", + "nxdn_mode" => "NXDN Modo", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Tipo de muestra", + "mode_hangtime" => "Modo tiempo de suspension", + // Config Page - General Configuration + "node_call" => "Nodo signo de llamada", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radio Frecuencia", + "lattitude" => "Latitud", + "longitude" => "Longitud", + "town" => "Ciudad", + "country" => "Pais", + "url" => "URL", + "radio_type" => "Radio/Tipo modem", + "node_type" => "Nodo Tipo", + "timezone" => "Sistema zona horaria", + "dash_lang" => "Tablero de ldiomas", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister red", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ red", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master habilitar", + "dmr_cc" => "DMR Codigo de color", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 signo de llamada", + "dstar_rpt2" => "RPT2 signo de llamada", + "dstar_irc_password" => "ircDDBGateway contrasena", + "dstar_default_ref" => "Reflector predeterminado", + "aprs_host" => "APRS Host", + "dstar_irc_lang" => "ircDDBGateway Language", + "dstar_irc_time" => "Tiempo Anuncios", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Lanzamiento Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Lanzamiento Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Lanzamiento Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Tablero de acceso", + "fw_irc" => "ircDDBGateway Remoto", + "fw_ssh" => "SSH Acceso", + // Config Page - Password + "user" => "Usuario Nombre", + "password" => "Contrasena", + "set_password" => "Set contrasena", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Modos habilitado", + "net_status" => "Estatus de red", + "internet" => "Internet", + "radio_info" => "Radio Informacion", + "dstar_repeater" => "D-Star Repetidor", + "dstar_net" => "D-Star red", + "dmr_repeater" => "DMR Repetidor", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF red", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 red", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN red", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Time", + "mode" => "Modo", + "callsign" => "signo de llamada", + "target" => "Objetivo", + "src" => "Src", //version corta de "fuente" + "dur" => "Dur", //version corta de "duracion" + "loss" => "Perdida", + "ber" => "BER", //version corta de "Error de bit" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "Grupos", + "logoff" => "Finalizar", + "info" => "Informacion", + "utot" => "UTOT", //tiempo agotado para usuario + "gtot" => "GTOT", // tiempo agotado para grupo + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Ultimos 20 llamadas escuchadas atraves de este puerto", + "local_tx_list" => "Ultimo 20 llamadas que accesaron este puerto", + "active_starnet_groups" => "Activo grupo Starnet Groups", + "active_starnet_members" => "Activo miembros de grupo Starnet", + "d-star_link_manager" => "D-Star gestar de enlaces", + "d-star_link_status" => "D-Star Informacion de enlaces", + "service_status" => "Estado servicio" ); +?> diff --git a/lang/swedish_se.php b/lang/swedish_se.php index d8afba8..7f32cd7 100644 --- a/lang/swedish_se.php +++ b/lang/swedish_se.php @@ -6,152 +6,153 @@ // Uppdaterad: 02-Sep-2022 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voice", - "configuration" => "Konfiguration", - "dashboard_for" => "Dashboard för", - // Banner links - "dashboard" => "Dashboard", - "admin" => "Admin", - "power" => "Power", - "update" => "Uppdatera", - "backup_restore" => "Backup/Återställ", - "factory_reset" => "Fabriksåterställning", - "live_logs" => "Liveloggar", - // Config page section headdings - "hardware_info" => "Gateway Hårdvaruinformation", - "control_software" => "Kontroll Mjukvara", - "mmdvmhost_config" => "MMDVMHost Konfiguration", - "general_config" => "Generell Konfiguration", - "dmr_config" => "DMR Konfiguration", - "dstar_config" => "D-Star Konfiguration", - "ysf_config" => "Yaesu System Fusion Konfiguration", - "p25_config" => "P25 Konfiguration", - "nxdn_config" => "NXDN Konfiguration", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG Konfiguration", - "mobilegps_config" => "Mobil GPS Konfiguration", - "wifi_config" => "WiFi Konfiguration", - "fw_config" => "Brandvägg Konfiguration", - "remote_access_pw" => "Remote Access Password", - // Config Page - Section General - "setting" => "Inställning", - "value" => "Värde", - "apply" => "Spara", - // Config Page - Gateway Hardware Information - "hostname" => "Värdnamn", - "kernel" => "Kärna", - "platform" => "Plattform", - "cpu_load" => "CPU Last", - "cpu_temp" => "CPU Temp", - // Config Page - Control Software - "controller_software" => "Controller Software", - "controller_mode" => "Controller Mode", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Mode", - "d-star_mode" => "D-Star Mode", - "ysf_mode" => "YSF Mode", - "p25_mode" => "P25 Mode", - "nxdn_mode" => "NXDN Mode", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Displaytyp", - "mode_hangtime" => "Mode Hängtid", - // Config Page - General Configuration - "node_call" => "Node Signal", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "Radiofrekvens", - "lattitude" => "Latitud", - "longitude" => "Longitud", - "town" => "Stad", - "country" => "Land", - "url" => "URL", - "radio_type" => "Radio-/Modemtyp", - "node_type" => "Nodetyp", - "timezone" => "Systemets Tidzon", - "dash_lang" => "Dashboard Språk", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister Network", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ Network", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Enable", - "dmr_cc" => "DMR Colour Code", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 Signal", - "dstar_rpt2" => "RPT2 Signal", - "dstar_irc_password" => "Lösen ircDDB", - "dstar_default_ref" => "Default Reflektor", - "aprs_host" => "APRS-värd", - "dstar_irc_lang" => "ircDDBGateway Språk", - "dstar_irc_time" => "Tidsannonseringar", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF Startvärd", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 Startvärd", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN Startvärd", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobilGPS På", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Hastighet", - // Config Page - Firewall Configuration - "fw_dash" => "Dashboard Access", - "fw_irc" => "ircDDBGateway Remote", - "fw_ssh" => "SSH-access", - // Config Page - Password - "user" => "Användarnamn", - "password" => "Lösenord", - "set_password" => "Byt Lösenord", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Moder Aktiverade", - "net_status" => "Nätverkstatus", - "internet" => "Internet", - "radio_info" => "Radio Info", - "dstar_repeater" => "D-Star Repeater", - "dstar_net" => "D-Star Nätverk", - "dmr_repeater" => "DMR Repeater", - "dmr_master" => "DMR Master", - "ysf_net" => "YSF Nätverk", - "p25_radio" => "P25 Radio", - "p25_net" => "P25 Nätverk", - "nxdn_radio" => "NXDN Radio", - "nxdn_net" => "NXDN Nätverk", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Tid", - "mode" => "Mode", - "callsign" => "Signal", - "target" => "Mål", - "src" => "Src", // Short version of "Source" - "dur" => "Dur", // Short version of "Duration" - "loss" => "Loss", - "ber" => "BER", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gatewayaktivitet", - "pocsag_timeslot" => "Tidslucka", - "pocsag_msg" => "Meddelande", - // Dashboard - Extra Info - "group" => "Grupp", - "logoff" => "Logga Av", - "info" => "Information", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Gatewayaktivitet", - "local_tx_list" => "Lokal RF-aktivitet", - "active_starnet_groups" => "Aktiva Starnet Grupper", - "active_starnet_members" => "Aktiva Starnet Gruppmedlemmar", - "d-star_link_manager" => "D-Star Link Manager", - "d-star_link_status" => "D-Star Link Information", - "service_status" => "Service Status" + // Banner texts + "digital_voice" => "Digital Voice", + "configuration" => "Konfiguration", + "dashboard_for" => "Dashboard för", + // Banner links + "dashboard" => "Dashboard", + "admin" => "Admin", + "power" => "Power", + "update" => "Uppdatera", + "backup_restore" => "Backup/Återställ", + "factory_reset" => "Fabriksåterställning", + "live_logs" => "Liveloggar", + // Config page section headdings + "hardware_info" => "Gateway Hårdvaruinformation", + "control_software" => "Kontroll Mjukvara", + "mmdvmhost_config" => "MMDVMHost Konfiguration", + "general_config" => "Generell Konfiguration", + "dmr_config" => "DMR Konfiguration", + "dstar_config" => "D-Star Konfiguration", + "ysf_config" => "Yaesu System Fusion Konfiguration", + "p25_config" => "P25 Konfiguration", + "nxdn_config" => "NXDN Konfiguration", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Konfiguration", + "mobilegps_config" => "Mobil GPS Konfiguration", + "wifi_config" => "WiFi Konfiguration", + "fw_config" => "Brandvägg Konfiguration", + "remote_access_pw" => "Remote Access Password", + // Config Page - Section General + "setting" => "Inställning", + "value" => "Värde", + "apply" => "Spara", + // Config Page - Gateway Hardware Information + "hostname" => "Värdnamn", + "kernel" => "Kärna", + "platform" => "Plattform", + "cpu_load" => "CPU Last", + "cpu_temp" => "CPU Temp", + // Config Page - Control Software + "controller_software" => "Controller Software", + "controller_mode" => "Controller Mode", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Mode", + "d-star_mode" => "D-Star Mode", + "ysf_mode" => "YSF Mode", + "p25_mode" => "P25 Mode", + "nxdn_mode" => "NXDN Mode", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Displaytyp", + "mode_hangtime" => "Mode Hängtid", + // Config Page - General Configuration + "node_call" => "Node Signal", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "Radiofrekvens", + "lattitude" => "Latitud", + "longitude" => "Longitud", + "town" => "Stad", + "country" => "Land", + "url" => "URL", + "radio_type" => "Radio-/Modemtyp", + "node_type" => "Nodetyp", + "timezone" => "Systemets Tidzon", + "dash_lang" => "Dashboard Språk", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Colour Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Signal", + "dstar_rpt2" => "RPT2 Signal", + "dstar_irc_password" => "Lösen ircDDB", + "dstar_default_ref" => "Default Reflektor", + "aprs_host" => "APRS-värd", + "dstar_irc_lang" => "ircDDBGateway Språk", + "dstar_irc_time" => "Tidsannonseringar", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startvärd", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startvärd", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startvärd", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobilGPS På", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Hastighet", + // Config Page - Firewall Configuration + "fw_dash" => "Dashboard Access", + "fw_irc" => "ircDDBGateway Remote", + "fw_ssh" => "SSH-access", + // Config Page - Password + "user" => "Användarnamn", + "password" => "Lösenord", + "set_password" => "Byt Lösenord", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Moder Aktiverade", + "net_status" => "Nätverkstatus", + "internet" => "Internet", + "radio_info" => "Radio Info", + "dstar_repeater" => "D-Star Repeater", + "dstar_net" => "D-Star Nätverk", + "dmr_repeater" => "DMR Repeater", + "dmr_master" => "DMR Master", + "ysf_net" => "YSF Nätverk", + "p25_radio" => "P25 Radio", + "p25_net" => "P25 Nätverk", + "nxdn_radio" => "NXDN Radio", + "nxdn_net" => "NXDN Nätverk", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Tid", + "mode" => "Mode", + "callsign" => "Signal", + "target" => "Mål", + "src" => "Src", // Short version of "Source" + "dur" => "Dur", // Short version of "Duration" + "loss" => "Loss", + "ber" => "BER", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gatewayaktivitet", + "pocsag_timeslot" => "Tidslucka", + "pocsag_msg" => "Meddelande", + // Dashboard - Extra Info + "group" => "Grupp", + "logoff" => "Logga Av", + "info" => "Information", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Gatewayaktivitet", + "local_tx_list" => "Lokal RF-aktivitet", + "active_starnet_groups" => "Aktiva Starnet Grupper", + "active_starnet_members" => "Aktiva Starnet Gruppmedlemmar", + "d-star_link_manager" => "D-Star Link Manager", + "d-star_link_status" => "D-Star Link Information", + "service_status" => "Service Status" ); +?> diff --git a/lang/thai_th.php b/lang/thai_th.php index a9b8291..7579880 100644 --- a/lang/thai_th.php +++ b/lang/thai_th.php @@ -5,152 +5,153 @@ // Updated: 27July2018 // $lang = array ( - // Banner texts - "digital_voice" => "Digital Voice", - "configuration" => "ตั้งค่า", - "dashboard_for" => "แผงควบคุมสำหรับ", - // Banner links - "dashboard" => "แผงควบคุม", - "admin" => "ผู้ดูแล", - "power" => "เพาเวอร์", - "update" => "อัพเดท", - "backup_restore" => "สำรองข้อมูล", - "factory_reset" => "รีเซ็ต", - "live_logs" => "ประวัติการติดต่อ (สด)", - // Config page section headdings - "hardware_info" => "รายละเอียดของอุปกรณ์เกตเวย์", - "control_software" => "ซอฟต์แวร์ควบคุม", - "mmdvmhost_config" => "ตั้งค่า MMDVMHost", - "general_config" => "ตั้งค่าทั่วไป", - "dmr_config" => "ตั้งค่า DMR", - "dstar_config" => "ตั้งค่า D-Star", - "ysf_config" => "ตั้งค่า Yaesu System Fusion", - "p25_config" => "ตั้งค่า P25", - "nxdn_config" => "ตั้งค่า NXDN", - "m17_config" => "M17 Configuration", - "pocsag_config" => "ตั้งค่า POCSAG", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "ตั้งค่าวายฟาย", - "fw_config" => "ตั้งค่าระบบป้องกัน", - "remote_access_pw" => "ตั้งรหัสผ่าน", - // Config Page - Section General - "setting" => "ตั้งค่า", - "value" => "ค่า", - "apply" => "ยืนยัน", - // Config Page - Gateway Hardware Information - "hostname" => "ชื่ออุปกรณ์", - "kernel" => "เคอร์เนิล", - "platform" => "อุปกรณ์", - "cpu_load" => "โหลด CPU", - "cpu_temp" => "อุณหภูมิ CPU", - // Config Page - Control Software - "controller_software" => "ชนิดของอุปกรณ์", - "controller_mode" => "โหมดการทำงาน", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR", - "d-star_mode" => "D-Star", - "ysf_mode" => "YSF", - "p25_mode" => "P25", - "nxdn_mode" => "NXDN", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "หน้าจอ MMDVM", - "mode_hangtime" => "Hangtime", - // Config Page - General Configuration - "node_call" => "นามเรียกขานของสถานี", - "dmr_id" => "CCS7/DMR ID", - "radio_freq" => "ความถี่ที่ใช้งาน", - "lattitude" => "ละติจูด", - "longitude" => "ลองจิจูด", - "town" => "เมือง", - "country" => "ประเทศ", - "url" => "URL", - "radio_type" => "ชนิดของอุปกรณ์", - "node_type" => "รูปแบบของสถานี", - "timezone" => "เขตเวลาที่ใช้", - "dash_lang" => "ภาษาสำหรับแผงควบคุม", - // Config Page - DMR Configuration - "dmr_master" => "DMR Master (MMDVMHost)", - "bm_master" => "BrandMeister Master", - "bm_network" => "BrandMeister Network", - "dmr_plus_master" => "DMR+ Master", - "dmr_plus_network" => "DMR+ Network", - "xlx_master" => "XLX Master", - "xlx_enable" => "XLX Master Enable", - "dmr_cc" => "DMR Color Code", - "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", - "dmr_dumptadata" => "DMR DumpTAData", - // Config Page - D-Star Configuration - "dstar_rpt1" => "นามเรียกขาน RPT1", - "dstar_rpt2" => "นามเรียกขาน RPT2", - "dstar_irc_password" => "รหัสผ่านเข้าถึงจากภายนอก", - "dstar_default_ref" => "ค่าเริ่มต้นของ Reflector", - "aprs_host" => "เซิร์ฟเวอร์ APRS", - "dstar_irc_lang" => "ภาษาสำหรับ ircDDBGateway", - "dstar_irc_time" => "ประกาศเวลาทุกชั่วโมง", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF Startup Host", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 Startup Host", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN Startup Host", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "การเข้าถึงแผงควบคุม", - "fw_irc" => "การเข้าถึง ircDDBGateway", - "fw_ssh" => "การเข้าถึง SSH", - // Config Page - Password - "user" => "ชื่อผู้ใช้", - "password" => "รหัสผ่าน", - "set_password" => "ยืนยัน", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "โหมดที่เปิดใช้งาน", - "net_status" => "สถานะเครือข่าย", - "internet" => "อินเตอร์เน็ต", - "radio_info" => "ข้อมูลวิทยุ", - "dstar_repeater" => "รีพีทเตอร์ D-Star", - "dstar_net" => "เครือข่าย D-Star", - "dmr_repeater" => "รีพีทเตอร์ DMR", - "dmr_master" => "DMR Master", - "ysf_net" => "เครือข่าย YSF", - "p25_radio" => "วิทยุ P25", - "p25_net" => "เครือข่าย P25", - "nxdn_radio" => "วิทยุ NXDN", - "nxdn_net" => "เครือข่าย NXDN", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "เวลา", - "mode" => "โหมด", - "callsign" => "นามเรียกขาน", - "target" => "เป้าหมาย", - "src" => "สัญญาณจาก", // Short version of "Source" - "dur" => "ระยะเวลา", // Short version of "Duration" - "loss" => "สัญญาณสูญเสีย", - "ber" => "สัญญาณผิดพลาด", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Gateway Activity", - "pocsag_timeslot" => "Time Slot", - "pocsag_msg" => "Message", - // Dashboard - Extra Info - "group" => "กลุ่ม", - "logoff" => "ออกจากระบบ", - "info" => "ข้อมูล", - "utot" => "ผู้ใช้", // Short for User Timeout - "gtot" => "กลุ่ม", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "ความเคลื่อนไหวของเกตเวย์", - "local_tx_list" => "ความเคลื่อนไหวของคลื่นที่รับได้", - "active_starnet_groups" => "Active Starnet Groups", - "active_starnet_members" => "Active Starnet Group Members", - "d-star_link_manager" => "จัดการการเชื่อมต่อของ D-Star", - "d-star_link_status" => "ข้อมูลการเชื่อมต่อของ D-Star", - "service_status" => "สถานะของระบบ" + // Banner texts + "digital_voice" => "Digital Voice", + "configuration" => "ตั้งค่า", + "dashboard_for" => "แผงควบคุมสำหรับ", + // Banner links + "dashboard" => "แผงควบคุม", + "admin" => "ผู้ดูแล", + "power" => "เพาเวอร์", + "update" => "อัพเดท", + "backup_restore" => "สำรองข้อมูล", + "factory_reset" => "รีเซ็ต", + "live_logs" => "ประวัติการติดต่อ (สด)", + // Config page section headdings + "hardware_info" => "รายละเอียดของอุปกรณ์เกตเวย์", + "control_software" => "ซอฟต์แวร์ควบคุม", + "mmdvmhost_config" => "ตั้งค่า MMDVMHost", + "general_config" => "ตั้งค่าทั่วไป", + "dmr_config" => "ตั้งค่า DMR", + "dstar_config" => "ตั้งค่า D-Star", + "ysf_config" => "ตั้งค่า Yaesu System Fusion", + "p25_config" => "ตั้งค่า P25", + "nxdn_config" => "ตั้งค่า NXDN", + "m17_config" => "M17 Configuration", + "pocsag_config" => "ตั้งค่า POCSAG", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "ตั้งค่าวายฟาย", + "fw_config" => "ตั้งค่าระบบป้องกัน", + "remote_access_pw" => "ตั้งรหัสผ่าน", + // Config Page - Section General + "setting" => "ตั้งค่า", + "value" => "ค่า", + "apply" => "ยืนยัน", + // Config Page - Gateway Hardware Information + "hostname" => "ชื่ออุปกรณ์", + "kernel" => "เคอร์เนิล", + "platform" => "อุปกรณ์", + "cpu_load" => "โหลด CPU", + "cpu_temp" => "อุณหภูมิ CPU", + // Config Page - Control Software + "controller_software" => "ชนิดของอุปกรณ์", + "controller_mode" => "โหมดการทำงาน", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR", + "d-star_mode" => "D-Star", + "ysf_mode" => "YSF", + "p25_mode" => "P25", + "nxdn_mode" => "NXDN", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "หน้าจอ MMDVM", + "mode_hangtime" => "Hangtime", + // Config Page - General Configuration + "node_call" => "นามเรียกขานของสถานี", + "dmr_id" => "CCS7/DMR ID", + "radio_freq" => "ความถี่ที่ใช้งาน", + "lattitude" => "ละติจูด", + "longitude" => "ลองจิจูด", + "town" => "เมือง", + "country" => "ประเทศ", + "url" => "URL", + "radio_type" => "ชนิดของอุปกรณ์", + "node_type" => "รูปแบบของสถานี", + "timezone" => "เขตเวลาที่ใช้", + "dash_lang" => "ภาษาสำหรับแผงควบคุม", + // Config Page - DMR Configuration + "dmr_master" => "DMR Master (MMDVMHost)", + "bm_master" => "BrandMeister Master", + "bm_network" => "BrandMeister Network", + "dmr_plus_master" => "DMR+ Master", + "dmr_plus_network" => "DMR+ Network", + "xlx_master" => "XLX Master", + "xlx_enable" => "XLX Master Enable", + "dmr_cc" => "DMR Color Code", + "dmr_embeddedlconly" => "DMR EmbeddedLCOnly", + "dmr_dumptadata" => "DMR DumpTAData", + // Config Page - D-Star Configuration + "dstar_rpt1" => "นามเรียกขาน RPT1", + "dstar_rpt2" => "นามเรียกขาน RPT2", + "dstar_irc_password" => "รหัสผ่านเข้าถึงจากภายนอก", + "dstar_default_ref" => "ค่าเริ่มต้นของ Reflector", + "aprs_host" => "เซิร์ฟเวอร์ APRS", + "dstar_irc_lang" => "ภาษาสำหรับ ircDDBGateway", + "dstar_irc_time" => "ประกาศเวลาทุกชั่วโมง", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF Startup Host", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 Startup Host", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN Startup Host", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "การเข้าถึงแผงควบคุม", + "fw_irc" => "การเข้าถึง ircDDBGateway", + "fw_ssh" => "การเข้าถึง SSH", + // Config Page - Password + "user" => "ชื่อผู้ใช้", + "password" => "รหัสผ่าน", + "set_password" => "ยืนยัน", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "โหมดที่เปิดใช้งาน", + "net_status" => "สถานะเครือข่าย", + "internet" => "อินเตอร์เน็ต", + "radio_info" => "ข้อมูลวิทยุ", + "dstar_repeater" => "รีพีทเตอร์ D-Star", + "dstar_net" => "เครือข่าย D-Star", + "dmr_repeater" => "รีพีทเตอร์ DMR", + "dmr_master" => "DMR Master", + "ysf_net" => "เครือข่าย YSF", + "p25_radio" => "วิทยุ P25", + "p25_net" => "เครือข่าย P25", + "nxdn_radio" => "วิทยุ NXDN", + "nxdn_net" => "เครือข่าย NXDN", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "เวลา", + "mode" => "โหมด", + "callsign" => "นามเรียกขาน", + "target" => "เป้าหมาย", + "src" => "สัญญาณจาก", // Short version of "Source" + "dur" => "ระยะเวลา", // Short version of "Duration" + "loss" => "สัญญาณสูญเสีย", + "ber" => "สัญญาณผิดพลาด", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Gateway Activity", + "pocsag_timeslot" => "Time Slot", + "pocsag_msg" => "Message", + // Dashboard - Extra Info + "group" => "กลุ่ม", + "logoff" => "ออกจากระบบ", + "info" => "ข้อมูล", + "utot" => "ผู้ใช้", // Short for User Timeout + "gtot" => "กลุ่ม", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "ความเคลื่อนไหวของเกตเวย์", + "local_tx_list" => "ความเคลื่อนไหวของคลื่นที่รับได้", + "active_starnet_groups" => "Active Starnet Groups", + "active_starnet_members" => "Active Starnet Group Members", + "d-star_link_manager" => "จัดการการเชื่อมต่อของ D-Star", + "d-star_link_status" => "ข้อมูลการเชื่อมต่อของ D-Star", + "service_status" => "สถานะของระบบ" ); +?> diff --git a/lang/turkish_tr.php b/lang/turkish_tr.php index f85ea62..d0b5316 100644 --- a/lang/turkish_tr.php +++ b/lang/turkish_tr.php @@ -5,152 +5,153 @@ // Updated: 27-JAN-2019 // $lang = array ( - // Banner texts - "digital_voice" => "Dijital Ses", - "configuration" => "Konfigürasyon", - "dashboard_for" => "Panosu", - // Banner links - "dashboard" => "Pano", - "admin" => "Yönetici", - "power" => "Güç", - "update" => "Güncelle", - "backup_restore" => "Yedekle/Geriyükle", - "factory_reset" => "Fabrika Ayarları", - "live_logs" => "Sistem Günlüğü", - // Config page section headdings - "hardware_info" => "Ağ Geçidi Donanım Bilgisi", - "control_software" => "Kontrolcü Yazılımı", - "mmdvmhost_config" => "MMDVMHost Konfigürasyonu", - "general_config" => "Genel Konfigürasyon", - "dmr_config" => "DMR Konfigürasyonu", - "dstar_config" => "D-Star Konfigürasyonu", - "ysf_config" => "Yaesu System Fusion Konfigürasyonu", - "p25_config" => "P25 Konfigürasyonu", - "nxdn_config" => "NXDN Konfigürasyonu", - "m17_config" => "M17 Configuration", - "pocsag_config" => "POCSAG Konfigürasyonu", - "mobilegps_config" => "Mobile GPS Configuration", - "wifi_config" => "Kablosuz Konfigürasyonu", - "fw_config" => "Güv.Duv. Konfigürasyonu", - "remote_access_pw" => "Uzak Erişim Parolası", - // Config Page - Section General - "setting" => "Ayar", - "value" => "Değer", - "apply" => "Değişiklikleri Uygula", - // Config Page - Gateway Hardware Information - "hostname" => "Sistem Adı", - "kernel" => "Çekirdek Sürümü", - "platform" => "Altyapı", - "cpu_load" => "CPU Kullanımı", - "cpu_temp" => "CPU Sıcaklığı", - // Config Page - Control Software - "controller_software" => "Kontrolcünün Yazılımı", - "controller_mode" => "Kontrolcünün Modu", - // Config Page - MMDVMHost Configuration - "dmr_mode" => "DMR Modu", - "d-star_mode" => "D-Star Modu", - "ysf_mode" => "YSF Modu", - "p25_mode" => "P25 Modu", - "nxdn_mode" => "NXDN Modu", - "m17_mode" => "M17 Mode", - "mmdvm_display" => "MMDVM Ekran Tipi", - "mode_hangtime" => "Mod Askı Süresi", - // Config Page - General Configuration - "node_call" => "Çağrı İşaretiniz", - "dmr_id" => "CCS7/DMR No", - "radio_freq" => "Radyo Frekansı", - "lattitude" => "Enlem", - "longitude" => "Boylam", - "town" => "Şehir", - "country" => "Ülke", - "url" => "URL", - "radio_type" => "Radyo/Modem Tipi", - "node_type" => "Yayın Tipi", - "timezone" => "Sistem Saati Dilimi", - "dash_lang" => "Pano Dili", - // Config Page - DMR Configuration - "dmr_master" => "DMR Sunucu (MMDVMHost)", - "bm_master" => "BrandMeister Sunucu", - "bm_network" => "BrandMeister Ağı", - "dmr_plus_master" => "DMR+ Sunucu", - "dmr_plus_network" => "DMR+ Ağı", - "xlx_master" => "XLX Sunucu", - "xlx_enable" => "XLX Sunucu Etkinleştirme", - "dmr_cc" => "DMR Renk Kodu", - "dmr_embeddedlconly" => "DMR GömülüLC", - "dmr_dumptadata" => "DMR TAVeriDökümü", - // Config Page - D-Star Configuration - "dstar_rpt1" => "RPT1 Çağrı İşareti", - "dstar_rpt2" => "RPT2 Çağrı İşareti", - "dstar_irc_password" => "Uzak Erişim Parolası", - "dstar_default_ref" => "Varsayılan Yansıtıcı", - "aprs_host" => "APRS Sunucusu", - "dstar_irc_lang" => "ircDDBAğGeçidi Dili", - "dstar_irc_time" => "Bildirimler", - // Config Page - YSF Configuration - "ysf_startup_host" => "YSF İşletme Ağı", - // Config Page - P25 Configuration - "p25_startup_host" => "P25 İşletme Ağı", - "p25_nac" => "P25 NAC", - // Config Page - NXDN Configuration - "nxdn_startup_host" => "NXDN İşletme Ağı", - "nxdn_ran" => "NXDN RAN", - // Config Page - M17 Configuration - "m17_startup_host" => "M17 Startup Host", - "m17_can" => "M17 CAN", - // Config Page - MobileGPS Configuration - "mobilegps_enable" => "MobileGPS Enable", - "mobilegps_port" => "GPS Port", - "mobilegps_speed" => "GPS Port Speed", - // Config Page - Firewall Configuration - "fw_dash" => "Pano Erişimi", - "fw_irc" => "ircDDBAğGeçidi Erişimi", - "fw_ssh" => "SSH Erişimi", - // Config Page - Password - "user" => "Kullanıcı Adı", - "password" => "Parola", - "set_password" => "Parolayı Uygula", - // Dashboard Front Page - Repeater Info Pannel - "modes_enabled" => "Etkin Modlar", - "net_status" => "Ağ Durumu", - "internet" => "İnternet", - "radio_info" => "Radyo Bilgisi", - "dstar_repeater" => "D-Star Röle", - "dstar_net" => "D-Star Ağı", - "dmr_repeater" => "DMR Röle", - "dmr_master" => "DMR Sunucu", - "ysf_net" => "YSF Ağı", - "p25_radio" => "P25 Radyo", - "p25_net" => "P25 Ağı", - "nxdn_radio" => "NXDN Radyo", - "nxdn_net" => "NXDN Ağı", - "m17_radio" => "M17 Radio", - "m17_net" => "M17 Network", - // Dashboard Front Page - Calls - "time" => "Zaman", - "mode" => "Mod", - "callsign" => "Çağrı İşareti", - "target" => "Hedef", - "src" => "Kynk", // Short version of "Source" - "dur" => "Süre", // Short version of "Duration" - "loss" => "Kayıp", - "ber" => "BHO", // Short version of "Bit Error Rate" - // POCSAG Specific - "pocsag_list" => "DAPNET Ağ Geçidi Etkinliği", - "pocsag_timeslot" => "Zaman Aralığı", - "pocsag_msg" => "Mesaj", - // Dashboard - Extra Info - "group" => "Grup", - "logoff" => "Oturum Kapat", - "info" => "Ayrıntılar", - "utot" => "UTOT", // Short for User Timeout - "gtot" => "GTOT", // Short for Group Timeout - // Dashboard Front Page / Admin - Section Headders - "last_heard_list" => "Ağ Geçidi Etkinliği", - "local_tx_list" => "Yerel RF Etkinliği", - "active_starnet_groups" => "Aktif Starnet Grupları", - "active_starnet_members" => "Aktif Starnet Grup Üyeleri", - "d-star_link_manager" => "D-Star Bağlantı Yöneticisi", - "d-star_link_status" => "D-Star Bağlantı Ayrıntıları", - "service_status" => "Servis Durumu" + // Banner texts + "digital_voice" => "Dijital Ses", + "configuration" => "Konfigürasyon", + "dashboard_for" => "Panosu", + // Banner links + "dashboard" => "Pano", + "admin" => "Yönetici", + "power" => "Güç", + "update" => "Güncelle", + "backup_restore" => "Yedekle/Geriyükle", + "factory_reset" => "Fabrika Ayarları", + "live_logs" => "Sistem Günlüğü", + // Config page section headdings + "hardware_info" => "Ağ Geçidi Donanım Bilgisi", + "control_software" => "Kontrolcü Yazılımı", + "mmdvmhost_config" => "MMDVMHost Konfigürasyonu", + "general_config" => "Genel Konfigürasyon", + "dmr_config" => "DMR Konfigürasyonu", + "dstar_config" => "D-Star Konfigürasyonu", + "ysf_config" => "Yaesu System Fusion Konfigürasyonu", + "p25_config" => "P25 Konfigürasyonu", + "nxdn_config" => "NXDN Konfigürasyonu", + "m17_config" => "M17 Configuration", + "pocsag_config" => "POCSAG Konfigürasyonu", + "mobilegps_config" => "Mobile GPS Configuration", + "wifi_config" => "Kablosuz Konfigürasyonu", + "fw_config" => "Güv.Duv. Konfigürasyonu", + "remote_access_pw" => "Uzak Erişim Parolası", + // Config Page - Section General + "setting" => "Ayar", + "value" => "Değer", + "apply" => "Değişiklikleri Uygula", + // Config Page - Gateway Hardware Information + "hostname" => "Sistem Adı", + "kernel" => "Çekirdek Sürümü", + "platform" => "Altyapı", + "cpu_load" => "CPU Kullanımı", + "cpu_temp" => "CPU Sıcaklığı", + // Config Page - Control Software + "controller_software" => "Kontrolcünün Yazılımı", + "controller_mode" => "Kontrolcünün Modu", + // Config Page - MMDVMHost Configuration + "dmr_mode" => "DMR Modu", + "d-star_mode" => "D-Star Modu", + "ysf_mode" => "YSF Modu", + "p25_mode" => "P25 Modu", + "nxdn_mode" => "NXDN Modu", + "m17_mode" => "M17 Mode", + "mmdvm_display" => "MMDVM Ekran Tipi", + "mode_hangtime" => "Mod Askı Süresi", + // Config Page - General Configuration + "node_call" => "Çağrı İşaretiniz", + "dmr_id" => "CCS7/DMR No", + "radio_freq" => "Radyo Frekansı", + "lattitude" => "Enlem", + "longitude" => "Boylam", + "town" => "Şehir", + "country" => "Ülke", + "url" => "URL", + "radio_type" => "Radyo/Modem Tipi", + "node_type" => "Yayın Tipi", + "timezone" => "Sistem Saati Dilimi", + "dash_lang" => "Pano Dili", + // Config Page - DMR Configuration + "dmr_master" => "DMR Sunucu (MMDVMHost)", + "bm_master" => "BrandMeister Sunucu", + "bm_network" => "BrandMeister Ağı", + "dmr_plus_master" => "DMR+ Sunucu", + "dmr_plus_network" => "DMR+ Ağı", + "xlx_master" => "XLX Sunucu", + "xlx_enable" => "XLX Sunucu Etkinleştirme", + "dmr_cc" => "DMR Renk Kodu", + "dmr_embeddedlconly" => "DMR GömülüLC", + "dmr_dumptadata" => "DMR TAVeriDökümü", + // Config Page - D-Star Configuration + "dstar_rpt1" => "RPT1 Çağrı İşareti", + "dstar_rpt2" => "RPT2 Çağrı İşareti", + "dstar_irc_password" => "Uzak Erişim Parolası", + "dstar_default_ref" => "Varsayılan Yansıtıcı", + "aprs_host" => "APRS Sunucusu", + "dstar_irc_lang" => "ircDDBAğGeçidi Dili", + "dstar_irc_time" => "Bildirimler", + // Config Page - YSF Configuration + "ysf_startup_host" => "YSF İşletme Ağı", + // Config Page - P25 Configuration + "p25_startup_host" => "P25 İşletme Ağı", + "p25_nac" => "P25 NAC", + // Config Page - NXDN Configuration + "nxdn_startup_host" => "NXDN İşletme Ağı", + "nxdn_ran" => "NXDN RAN", + // Config Page - M17 Configuration + "m17_startup_host" => "M17 Startup Host", + "m17_can" => "M17 CAN", + // Config Page - MobileGPS Configuration + "mobilegps_enable" => "MobileGPS Enable", + "mobilegps_port" => "GPS Port", + "mobilegps_speed" => "GPS Port Speed", + // Config Page - Firewall Configuration + "fw_dash" => "Pano Erişimi", + "fw_irc" => "ircDDBAğGeçidi Erişimi", + "fw_ssh" => "SSH Erişimi", + // Config Page - Password + "user" => "Kullanıcı Adı", + "password" => "Parola", + "set_password" => "Parolayı Uygula", + // Dashboard Front Page - Repeater Info Pannel + "modes_enabled" => "Etkin Modlar", + "net_status" => "Ağ Durumu", + "internet" => "İnternet", + "radio_info" => "Radyo Bilgisi", + "dstar_repeater" => "D-Star Röle", + "dstar_net" => "D-Star Ağı", + "dmr_repeater" => "DMR Röle", + "dmr_master" => "DMR Sunucu", + "ysf_net" => "YSF Ağı", + "p25_radio" => "P25 Radyo", + "p25_net" => "P25 Ağı", + "nxdn_radio" => "NXDN Radyo", + "nxdn_net" => "NXDN Ağı", + "m17_radio" => "M17 Radio", + "m17_net" => "M17 Network", + // Dashboard Front Page - Calls + "time" => "Zaman", + "mode" => "Mod", + "callsign" => "Çağrı İşareti", + "target" => "Hedef", + "src" => "Kynk", // Short version of "Source" + "dur" => "Süre", // Short version of "Duration" + "loss" => "Kayıp", + "ber" => "BHO", // Short version of "Bit Error Rate" + // POCSAG Specific + "pocsag_list" => "DAPNET Ağ Geçidi Etkinliği", + "pocsag_timeslot" => "Zaman Aralığı", + "pocsag_msg" => "Mesaj", + // Dashboard - Extra Info + "group" => "Grup", + "logoff" => "Oturum Kapat", + "info" => "Ayrıntılar", + "utot" => "UTOT", // Short for User Timeout + "gtot" => "GTOT", // Short for Group Timeout + // Dashboard Front Page / Admin - Section Headders + "last_heard_list" => "Ağ Geçidi Etkinliği", + "local_tx_list" => "Yerel RF Etkinliği", + "active_starnet_groups" => "Aktif Starnet Grupları", + "active_starnet_members" => "Aktif Starnet Grup Üyeleri", + "d-star_link_manager" => "D-Star Bağlantı Yöneticisi", + "d-star_link_status" => "D-Star Bağlantı Ayrıntıları", + "service_status" => "Servis Durumu" ); +?> diff --git a/mmdvmhost/bm_links.php b/mmdvmhost/bm_links.php index c4822b9..0cdfb09 100644 --- a/mmdvmhost/bm_links.php +++ b/mmdvmhost/bm_links.php @@ -1,34 +1,4 @@ = 200 ) { $bmAPIkeyV2 = $bmAPIkey; unset($bmAPIkey); } } - + //Load the dmrgateway config file $dmrGatewayConfigFile = '/etc/dmrgateway'; if (fopen($dmrGatewayConfigFile,'r')) { $configdmrgateway = parse_ini_file($dmrGatewayConfigFile, true); } @@ -89,24 +59,17 @@ if ( $testMMDVModeDMR == 1 ) { $bmStaticTGList = ""; $bmDynamicTGList = ""; - // Pull the information from JSON. talkgroup/slot are documented - // as integers in the BrandMeister API but PHP's json_decode - // doesn't enforce that — cast to (int) so a hostile / compromised - // upstream response can't smuggle HTML/JS into the rendered - // bytes below. (int) of a non-numeric string is 0, which renders - // as plain "0" — predictable, inert. + // Pull the information form JSON if (isset($json->staticSubscriptions)) { $bmStaticTGListJson = $json->staticSubscriptions; foreach($bmStaticTGListJson as $staticTG) { - $tgNum = (int)$staticTG->talkgroup; - $tgSlot = (int)$staticTG->slot; - if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) && $tgSlot === 1) { - $bmStaticTGList .= "TG".$tgNum."(".$tgSlot.") "; + if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) && $staticTG->slot == "1") { + $bmStaticTGList .= "TG".$staticTG->talkgroup."(".$staticTG->slot.") "; } - else if (getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $tgSlot === 2) { - $bmStaticTGList .= "TG".$tgNum."(".$tgSlot.") "; + else if (getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $staticTG->slot == "2") { + $bmStaticTGList .= "TG".$staticTG->talkgroup."(".$staticTG->slot.") "; } - else if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" && getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $tgSlot === 0) { - $bmStaticTGList .= "TG".$tgNum." "; + else if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" && getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $staticTG->slot == "0") { + $bmStaticTGList .= "TG".$staticTG->talkgroup." "; } } $bmStaticTGList = wordwrap($bmStaticTGList, 15, "
\n"); @@ -114,16 +77,14 @@ if ( $testMMDVModeDMR == 1 ) { } else { $bmStaticTGList = "None"; } if (isset($json->dynamicSubscriptions)) { $bmDynamicTGListJson = $json->dynamicSubscriptions; foreach($bmDynamicTGListJson as $dynamicTG) { - $tgNum = (int)$dynamicTG->talkgroup; - $tgSlot = (int)$dynamicTG->slot; - if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) && $tgSlot === 1) { - $bmDynamicTGList .= "TG".$tgNum."(".$tgSlot.") "; + if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) && $dynamicTG->slot == "1") { + $bmDynamicTGList .= "TG".$dynamicTG->talkgroup."(".$dynamicTG->slot.") "; } - else if (getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $tgSlot === 2) { - $bmDynamicTGList .= "TG".$tgNum."(".$tgSlot.") "; + else if (getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $dynamicTG->slot == "2") { + $bmDynamicTGList .= "TG".$dynamicTG->talkgroup."(".$dynamicTG->slot.") "; } - else if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" && getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $tgSlot === 0) { - $bmDynamicTGList .= "TG".$tgNum." "; + else if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" && getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) && $dynamicTG->slot == "0") { + $bmDynamicTGList .= "TG".$dynamicTG->talkgroup." "; } } $bmDynamicTGList = wordwrap($bmDynamicTGList, 15, "
\n"); @@ -140,13 +101,8 @@ if ( $testMMDVModeDMR == 1 ) { '."\n"; echo ' '."\n"; - // $dmrMasterHost / $dmrID come from /etc/dmrgateway — operator - // edits via the expert editor. htmlspecialchars defence-in-depth. - // $bmStatic/DynamicTGList already contain wordwrap-injected `
` - // tags by design, so they intentionally aren't escaped here; the - // talkgroup/slot integers inside them were cast to (int) above. - echo ' '.htmlspecialchars((string)$dmrMasterHost, ENT_QUOTES, 'UTF-8').''; - echo ''.htmlspecialchars((string)$dmrID, ENT_QUOTES, 'UTF-8').''; + echo ' '.$dmrMasterHost.''; + echo ''.$dmrID.''; echo ''.$bmStaticTGList.''; echo ''.$bmDynamicTGList.''; echo ''."\n"; @@ -154,3 +110,4 @@ if ( $testMMDVModeDMR == 1 ) { echo '
'."\n"; } } +?> diff --git a/mmdvmhost/bm_manager.php b/mmdvmhost/bm_manager.php index e036540..44efd80 100644 --- a/mmdvmhost/bm_manager.php +++ b/mmdvmhost/bm_manager.php @@ -1,29 +1,4 @@ $targetSlot, - 'group' => $targetTG + 'group' => $targetTG ); $postData = json_encode($postDataTG); $postHeaders[] = 'Content-Length: '.strlen($postData); @@ -136,7 +111,6 @@ if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Stop this working outside o if (isset($bmAPIkeyV2)) { echo 'BrandMeister Manager'."\n"; echo '
'."\n"; - echo csrf_field_html()."\n"; echo ''."\n"; echo ' @@ -161,4 +135,3 @@ if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Stop this working outside o } } - diff --git a/mmdvmhost/index.php b/mmdvmhost/index.php index 702d3d1..e69de29 100644 --- a/mmdvmhost/index.php +++ b/mmdvmhost/index.php @@ -1,3 +0,0 @@ -setTimeZone($local_tz); - $local_time = $dt->format('H:i:s M jS'); + $listElem = $localTXList[$i]; + if ($listElem[5] == "RF" && ($listElem[1] == "D-Star" || startsWith($listElem[1], "DMR") || $listElem[1] == "YSF" || $listElem[1]== "P25" || $listElem[1]== "NXDN" || $listElem[1]== "M17")) { + if ($counter <= 19) { //last 20 calls + $utc_time = $listElem[0]; + $utc_tz = new DateTimeZone('UTC'); + $local_tz = new DateTimeZone(date_default_timezone_get ()); + $dt = new DateTime($utc_time, $utc_tz); + $dt->setTimeZone($local_tz); + $local_time = $dt->format('H:i:s M jS'); + 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 { + if (strpos($listElem[2],"-") > 0) { $listElem[2] = substr($listElem[2], 0, strpos($listElem[2],"-")); } + if ($listElem[3] && $listElem[3] != ' ' ) { + echo ""; + } else { + echo ""; + } + } + if (strlen($listElem[4]) == 1) { $listElem[4] = str_pad($listElem[4], 8, " ", STR_PAD_LEFT); } + 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 { + echo""; //duration + + // 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 ""; } - // Same normalisation pattern as mmdvmhost/lh.php — every - // value below comes from log-line parsing of RF traffic - // and could carry hostile bytes from a transmitting - // station. See the note in lh.php for the rationale. - $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'); - $tgtRaw = (string)$listElem[4]; - 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'); - $ber = htmlspecialchars((string)(isset($listElem[8]) ? $listElem[8] : ''), ENT_QUOTES, 'UTF-8'); - $rssi = htmlspecialchars((string)(isset($listElem[9]) ? $listElem[9] : ''), 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 { - $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 ""; - } - } - 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 { - echo ""; //duration - - // 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 ""; //rssi - } - echo "\n"; - $counter++; } - } - } + echo""; //rssi + } + echo "\n"; + $counter++; } + } + } ?>
$local_time".str_replace('Slot ', 'TS', $listElem[1])."$listElem[2]".$listElem[2]."$listElem[2]
$listElem[2]/$listElem[3]
(GPS)
(GPS)
".str_replace(" "," ", $listElem[4])."RF$listElem[5]TX " . $duration_string . " secDMR Data$listElem[6]$listElem[8]$listElem[8]$listElem[8]$listElem[8]
$local_time$modeHtml$cs$cs$cs
$csTrimHtml/$csSuffix
(GPS)
(GPS)
".str_replace(' ', ' ', $tgtHtml)."RF$srcTX " . $duration_string . " secDMR Data$dur$ber$ber$ber$ber$rssi
$listElem[9]
- - diff --git a/mmdvmhost/m17_manager.php b/mmdvmhost/m17_manager.php index 7abbf10..ea25bd4 100644 --- a/mmdvmhost/m17_manager.php +++ b/mmdvmhost/m17_manager.php @@ -1,168 +1,142 @@ Reflector - * ` against the M17Gateway remote-control port - * configured in /etc/m17gateway. After action, triggers a 2 s - * `setTimeout` reload. - * - * Inputs read at render time: - * /etc/m17gateway Confirms the gateway is configured. - * /usr/local/etc/M17Hosts.txt + optional /root/M17Hosts.txt for the - * operator's reflector picklist. - * - * NOTE for the security pass: validation is whitelist-regex; no - * setEmbeddableSecurityHeaders() call in this file. Coverage gap. - */ - if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Stop this working outside of the admin page - include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config - include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools - include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDash Functions - include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code + include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config + include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools + include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDash Functions + include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code - // Check if M17 is Enabled - $testMMDVModeM17 = getConfigItem("M17 Network", "Enable", $mmdvmconfigs); - if ( $testMMDVModeM17 == 1 ) { + // Check if M17 is Enabled + $testMMDVModeM17 = getConfigItem("M17 Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeM17 == 1 ) { - //Load the m17gateway config file - $m17GatewayConfigFile = '/etc/m17gateway'; - if (fopen($m17GatewayConfigFile,'r')) { $configm17gateway = parse_ini_file($m17GatewayConfigFile, true); } + //Load the m17gateway config file + $m17GatewayConfigFile = '/etc/m17gateway'; + if (fopen($m17GatewayConfigFile,'r')) { $configm17gateway = parse_ini_file($m17GatewayConfigFile, true); } - // Check that the remote is enabled - if ( $configm17gateway['Remote Commands']['Enable'] == 1 ) { - $remotePort = $configm17gateway['Remote Commands']['Port']; - if (!empty($_POST) && isset($_POST["m17MgrSubmit"])) { - // Handle Posted Data - if (preg_match('/[^A-Za-z0-9-]/',$_POST['m17LinkHost'])) { unset ($_POST['m17LinkHost']); unset ($_POST['m17LinkRoom']); } - if (preg_match('/[^A-Z]/',$_POST['m17LinkRoom'])) { unset ($_POST['m17LinkHost']); unset ($_POST['m17LinkRoom']); } - if ($_POST["Link"] == "LINK") { - if ($_POST['m17LinkHost'] == "none") { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." Reflector unlink"; - } else { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." Reflector ".$_POST['m17LinkHost']." ".$_POST['m17LinkRoom']; - } - } elseif ($_POST["Link"] == "UNLINK") { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." Reflector unlink"; - } else { - echo "M17 Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; - echo "
\n
\n"; - unset($_POST); - echo ''; - } - if (empty($_POST['m17LinkHost'])) { - echo "M17 Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Somthing wrong with your input, (No target specified) - please try again"; - echo "
\n
\n"; - unset($_POST); - echo ''; - } - if (isset($remoteCommand)) { - echo "M17 Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo htmlspecialchars((string)exec($remoteCommand), ENT_QUOTES, 'UTF-8'); - echo "
\n
\n"; - echo ''; - } - } else { - // Output HTML - ?> - M17 Link Manager - - - - - - - - - - - - - -
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
- - - - Link - UnLink - - -
- -
- M17 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (empty($_POST['m17LinkHost'])) { + echo "M17 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (No target specified) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (isset($remoteCommand)) { + echo "M17 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($remoteCommand); + echo "
\n
\n"; + echo ''; + } + } else { + // Output HTML + ?> + M17 Link Manager +
+ + + + + + + + + + + +
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + + + Link + UnLink + + +
+
+
+ diff --git a/mmdvmhost/nxdn_manager.php b/mmdvmhost/nxdn_manager.php index f5384fe..efa5747 100644 --- a/mmdvmhost/nxdn_manager.php +++ b/mmdvmhost/nxdn_manager.php @@ -1,138 +1,114 @@ TalkGroup - * ` against the NXDNGateway remote-control port - * configured in /etc/nxdngateway. Triggers a 2 s `setTimeout` reload. - * - * Inputs: - * /etc/nxdngateway Gateway config + remote port. - * /usr/local/etc/NXDNHosts.txt Operator picklist. - * /usr/local/etc/NXDNHostsLocal.txt Local additions (optional). - * - * NOTE for the security pass: validation is whitelist-regex; no - * setEmbeddableSecurityHeaders() call in this file. Coverage gap. - */ - if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Stop this working outside of the admin page - include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config - include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools - include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDash Functions - include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code + include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config + include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools + include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDash Functions + include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code - // Check if NXDN is Enabled - $testMMDVModeNXDN = getConfigItem("NXDN Network", "Enable", $mmdvmconfigs); - if ( $testMMDVModeNXDN == 1 ) { + // Check if NXDN is Enabled + $testMMDVModeNXDN = getConfigItem("NXDN Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeNXDN == 1 ) { - //Load the nxdngateway config file - $nxdnGatewayConfigFile = '/etc/nxdngateway'; - if (fopen($nxdnGatewayConfigFile,'r')) { $confignxdngateway = parse_ini_file($nxdnGatewayConfigFile, true); } + //Load the nxdngateway config file + $nxdnGatewayConfigFile = '/etc/nxdngateway'; + if (fopen($nxdnGatewayConfigFile,'r')) { $confignxdngateway = parse_ini_file($nxdnGatewayConfigFile, true); } - // Check that the remote is enabled - if ( $confignxdngateway['Remote Commands']['Enable'] == 1 ) { - $remotePort = $confignxdngateway['Remote Commands']['Port']; - if (!empty($_POST) && isset($_POST["nxdnMgrSubmit"])) { - // Handle Posted Data - if (preg_match('/[^A-Za-z0-9]/',$_POST['nxdnLinkHost'])) { unset ($_POST['nxdnLinkHost']);} - if ($_POST["Link"] == "LINK") { - if ($_POST['nxdnLinkHost'] == "none") { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." TalkGroup unlink"; - } else { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." TalkGroup ".$_POST['nxdnLinkHost']; - } - } elseif ($_POST["Link"] == "UNLINK") { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." TalkGroup unlink"; - } else { - echo "NXDN Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; - echo "
\n
\n"; - unset($_POST); - echo ''; - } - if (empty($_POST['nxdnLinkHost'])) { - echo "NXDN Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Somthing wrong with your input, (No target specified) - please try again"; - echo "
\n
\n"; - unset($_POST); - echo ''; - } - if (isset($remoteCommand)) { - echo "NXDN Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo htmlspecialchars((string)exec($remoteCommand), ENT_QUOTES, 'UTF-8'); - echo "
\n
\n"; - echo ''; - } - } else { - // Output HTML - ?> - NXDN Link Manager -
- - - - - - - - - - - - -
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
- - - Link - UnLink - - -
-
-
- NXDN Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (empty($_POST['nxdnLinkHost'])) { + echo "NXDN Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (No target specified) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (isset($remoteCommand)) { + echo "NXDN Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($remoteCommand); + echo "
\n
\n"; + echo ''; + } + } else { + // Output HTML + ?> + NXDN Link Manager +
+ + + + + + + + + + + +
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + + Link + UnLink + + +
+
+
+ diff --git a/mmdvmhost/p25_manager.php b/mmdvmhost/p25_manager.php index ed63f1a..425fdcc 100644 --- a/mmdvmhost/p25_manager.php +++ b/mmdvmhost/p25_manager.php @@ -1,140 +1,115 @@ TalkGroup - * ` against the P25Gateway remote-control port configured - * in /etc/p25gateway. Triggers a 2 s `setTimeout` reload. - * - * Inputs: - * /etc/p25gateway Gateway config + remote port. - * /usr/local/etc/P25Hosts.txt Operator picklist. - * /usr/local/etc/P25HostsLocal.txt Local additions (optional). - * - * NOTE for the security pass: validation is whitelist-regex; no - * setEmbeddableSecurityHeaders() call in this file. Coverage gap. - */ - if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Stop this working outside of the admin page - include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config - include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools - include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDash Functions - include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code + include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config + include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools + include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDash Functions + include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code - // Check if P25 is Enabled - $testMMDVModeP25 = getConfigItem("P25 Network", "Enable", $mmdvmconfigs); - if ( $testMMDVModeP25 == 1 ) { + // Check if P25 is Enabled + $testMMDVModeP25 = getConfigItem("P25 Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeP25 == 1 ) { - //Load the p25gateway config file - $p25GatewayConfigFile = '/etc/p25gateway'; - if (fopen($p25GatewayConfigFile,'r')) { $configp25gateway = parse_ini_file($p25GatewayConfigFile, true); } + //Load the p25gateway config file + $p25GatewayConfigFile = '/etc/p25gateway'; + if (fopen($p25GatewayConfigFile,'r')) { $configp25gateway = parse_ini_file($p25GatewayConfigFile, true); } - // Check that the remote is enabled - if ( $configp25gateway['Remote Commands']['Enable'] == 1 ) { - $remotePort = $configp25gateway['Remote Commands']['Port']; - if (!empty($_POST) && isset($_POST["p25MgrSubmit"])) { - // Handle Posted Data - if (preg_match('/[^A-Za-z0-9]/',$_POST['p25LinkHost'])) { unset ($_POST['p25LinkHost']);} - if ($_POST["Link"] == "LINK") { - if ($_POST['p25LinkHost'] == "none") { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." TalkGroup 9999"; - } else { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." TalkGroup ".$_POST['p25LinkHost']; - } - } elseif ($_POST["Link"] == "UNLINK") { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." TalkGroup 9999"; - } else { - echo "P25 Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; - echo "
\n
\n"; - unset($_POST); - echo ''; - } - if (empty($_POST['p25LinkHost'])) { - echo "P25 Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Somthing wrong with your input, (No target specified) - please try again"; - echo "
\n
\n"; - unset($_POST); - echo ''; - } - if (isset($remoteCommand)) { - echo "P25 Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo htmlspecialchars((string)exec($remoteCommand), ENT_QUOTES, 'UTF-8'); - echo "
\n
\n"; - echo ''; - } - } else { - // Output HTML - ?> - P25 Link Manager -
- - - - - - - - - - - - -
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
- - Link - UnLink - - -
-
-
- P25 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (empty($_POST['p25LinkHost'])) { + echo "P25 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (No target specified) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (isset($remoteCommand)) { + echo "P25 Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($remoteCommand); + echo "
\n
\n"; + echo ''; + } + } else { + // Output HTML + ?> + P25 Link Manager +
+ + + + + + + + + + + +
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + Link + UnLink + + +
+
+
+ diff --git a/mmdvmhost/pages.php b/mmdvmhost/pages.php index 8fad9d7..19c8822 100644 --- a/mmdvmhost/pages.php +++ b/mmdvmhost/pages.php @@ -1,33 +1,6 @@ " preview where applicable. - * - * Data flow: parses the in-memory `$logLinesDAPNETGateway` array - * populated by mmdvmhost/functions.php from - * /var/log/pi-star/DAPNETGateway-YYYY-MM-DD.log. - * - * Most of the work here contributed by geeks4hire (Ben Horan); Skyper - * decode added by Andy Taylor (MW0MWZ). - */ - - -// AJAX-loaded partial — embeddable variant only. The earlier -// duplicate setSecurityHeaders() call has been removed; that -// non-embeddable variant raced with this one and won via the -// headers_sent() guard, so the file was effectively shipping -// X-Frame-Options / frame-ancestors despite the embeddable -// version being added below it. -require_once($_SERVER['DOCUMENT_ROOT'] . '/config/security_headers.php'); -setEmbeddableSecurityHeaders(); +// Most of the work here contributed by geeks4hire (Ben Horan) +// Skyper decode by Andy Taylor (MW0MWZ) include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools @@ -35,8 +8,7 @@ include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDa include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code // Function to reverse the ROT1 used for Skyper -function un_rot($message) -{ +function un_rot($message) { $output = ""; $messageTextArray = str_split($message); @@ -53,8 +25,7 @@ function un_rot($message) } // Function to handle Skyper Messages -function skyper($message, $pocsagric) -{ +function skyper($message, $pocsagric) { $output = ""; $messageTextArray = str_split($message); @@ -93,7 +64,7 @@ function skyper($message, $pocsagric) $skyperMsgNr = ord($messageTextArray[1]) - 32; unset($messageTextArray[1]); } - + if (count($messageTextArray) >= 1) { // Check to see if there is a message to decode $output = "[Skyper Rubric:$skyperRubric Msg:$skyperMsgNr] ".un_rot(implode($messageTextArray)); } @@ -149,7 +120,7 @@ function skyper($message, $pocsagric) if (isset($pocsag_timeslot)) { $pocsag_timeslot = htmlspecialchars($pocsag_timeslot, ENT_QUOTES, 'UTF-8'); } if (isset($pocsag_ric)) { $pocsag_ric = htmlspecialchars($pocsag_ric, ENT_QUOTES, 'UTF-8'); } if (isset($pocsag_msg)) { $pocsag_msg = htmlspecialchars($pocsag_msg, ENT_QUOTES, 'UTF-8'); } - + ?> @@ -164,4 +135,3 @@ function skyper($message, $pocsagric) ?> - diff --git a/mmdvmhost/repeaterinfo.php b/mmdvmhost/repeaterinfo.php index c831574..638e664 100644 --- a/mmdvmhost/repeaterinfo.php +++ b/mmdvmhost/repeaterinfo.php @@ -1,44 +1,8 @@ 0) - $configdstar[$key1] = $value1; - } + if (strpos($line1, '=') !== false) { + list($key1,$value1) = preg_split('/=/',$line1); + $value1 = trim(str_replace('"','',$value1)); + if (strlen($value1) > 0) + $configdstar[$key1] = $value1; + } } } @@ -77,28 +41,28 @@ if (fopen($dapnetGatewayConfigFile,'r')) { $configdapnetgateway = parse_ini_file // Load the ysf2dmr config file if (file_exists('/etc/ysf2dmr')) { - $ysf2dmrConfigFile = '/etc/ysf2dmr'; - if (fopen($ysf2dmrConfigFile,'r')) { $configysf2dmr = parse_ini_file($ysf2dmrConfigFile, true); } + $ysf2dmrConfigFile = '/etc/ysf2dmr'; + if (fopen($ysf2dmrConfigFile,'r')) { $configysf2dmr = parse_ini_file($ysf2dmrConfigFile, true); } } // Load the ysf2nxdn config file if (file_exists('/etc/ysf2nxdn')) { - $ysf2nxdnConfigFile = '/etc/ysf2nxdn'; - if (fopen($ysf2nxdnConfigFile,'r')) { $configysf2nxdn = parse_ini_file($ysf2nxdnConfigFile, true); } + $ysf2nxdnConfigFile = '/etc/ysf2nxdn'; + if (fopen($ysf2nxdnConfigFile,'r')) { $configysf2nxdn = parse_ini_file($ysf2nxdnConfigFile, true); } } // Load the ysf2p25 config file if (file_exists('/etc/ysf2p25')) { - $ysf2p25ConfigFile = '/etc/ysf2p25'; - if (fopen($ysf2p25ConfigFile,'r')) { $configysf2p25 = parse_ini_file($ysf2p25ConfigFile, true); } + $ysf2p25ConfigFile = '/etc/ysf2p25'; + if (fopen($ysf2p25ConfigFile,'r')) { $configysf2p25 = parse_ini_file($ysf2p25ConfigFile, true); } } // Load the dmr2ysf config file if (file_exists('/etc/dmr2ysf')) { - $dmr2ysfConfigFile = '/etc/dmr2ysf'; - if (fopen($dmr2ysfConfigFile,'r')) { $configdmr2ysf = parse_ini_file($dmr2ysfConfigFile, true); } + $dmr2ysfConfigFile = '/etc/dmr2ysf'; + if (fopen($dmr2ysfConfigFile,'r')) { $configdmr2ysf = parse_ini_file($dmr2ysfConfigFile, true); } } // Load the dmr2nxdn config file if (file_exists('/etc/dmr2nxdn')) { - $dmr2nxdnConfigFile = '/etc/dmr2nxdn'; - if (fopen($dmr2nxdnConfigFile,'r')) { $configdmr2nxdn = parse_ini_file($dmr2nxdnConfigFile, true); } + $dmr2nxdnConfigFile = '/etc/dmr2nxdn'; + if (fopen($dmr2nxdnConfigFile,'r')) { $configdmr2nxdn = parse_ini_file($dmr2nxdnConfigFile, true); } } ?> @@ -128,94 +92,80 @@ if (file_exists('/etc/dmr2nxdn')) { TrxTX " . htmlspecialchars((string)$listElem[1], ENT_QUOTES, 'UTF-8') . ""; - } - else { - if (getActualMode($lastHeard, $mmdvmconfigs) === 'idle') { - echo "Listening"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === NULL) { - if (isProcessRunning("MMDVMHost")) { echo "Listening"; } else { echo "OFFLINE"; } - } - elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'D-Star') { - echo "RX D-Star"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'D-Star') { - echo "Listening D-Star"; - } - elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'DMR') { - echo "RX DMR"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'DMR') { - echo "Listening DMR"; - } - elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'YSF') { - echo "RX YSF"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'YSF') { - echo "Listening YSF"; - } - elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'P25') { - echo "RX P25"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'P25') { - echo "Listening P25"; - } - elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'NXDN') { - echo "RX NXDN"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'NXDN') { - echo "Listening NXDN"; - } - elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'M17') { - echo "RX M17"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'M17') { - echo "Listening M17"; - } - elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'FM') { - echo "RX FM"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'FM') { - echo "Listening FM"; - } - elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'POCSAG') { - echo "POCSAG"; - } - else { - // getActualMode() returns log-derived strings; - // escape before HTML interpolation. - echo "" . htmlspecialchars((string)getActualMode($lastHeard, $mmdvmconfigs), ENT_QUOTES, 'UTF-8') . ""; - } - } - } + $listElem = $lastHeard[0]; + if ( $listElem[2] && $listElem[6] == null && $listElem[5] !== 'RF') { + echo "TX $listElem[1]"; + } + else { + if (getActualMode($lastHeard, $mmdvmconfigs) === 'idle') { + echo "Listening"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === NULL) { + if (isProcessRunning("MMDVMHost")) { echo "Listening"; } else { echo "OFFLINE"; } + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'D-Star') { + echo "RX D-Star"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'D-Star') { + echo "Listening D-Star"; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'DMR') { + echo "RX DMR"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'DMR') { + echo "Listening DMR"; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'YSF') { + echo "RX YSF"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'YSF') { + echo "Listening YSF"; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'P25') { + echo "RX P25"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'P25') { + echo "Listening P25"; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'NXDN') { + echo "RX NXDN"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'NXDN') { + echo "Listening NXDN"; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'M17') { + echo "RX M17"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'M17') { + echo "Listening M17"; + } + elseif ($listElem[2] && $listElem[6] == null && getActualMode($lastHeard, $mmdvmconfigs) === 'FM') { + echo "RX FM"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'FM') { + echo "Listening FM"; + } + elseif (getActualMode($lastHeard, $mmdvmconfigs) === 'POCSAG') { + echo "POCSAG"; + } + else { + echo "".getActualMode($lastHeard, $mmdvmconfigs).""; + } + } + } else { - echo ""; + echo ""; } ?> -Tx -Rx +Tx +Rx FW'.htmlspecialchars((string)$fwVersion, ENT_QUOTES, 'UTF-8').''."\n"; +if (getDVModemFirmware()) { +echo 'FW'.getDVModemFirmware().''."\n"; } ?> TCXO'.htmlspecialchars((string)$tcxoFreq, ENT_QUOTES, 'UTF-8').''."\n"; +if (getDVModemTCXOFreq()) { +echo 'TCXO'.getDVModemTCXOFreq().''."\n"; } ?> @@ -225,131 +175,117 @@ if ( $testMMDVModeDSTAR == 1 ) { //Hide the D-Star Reflector information when D- echo "
\n"; echo "\n"; echo "\n"; -// Config values from /etc/dstarrepeater and /etc/ircddbgateway -// — operator-controlled, but defensive escape before HTML -// interpolation. The legacy ` ` substitution stays but -// runs AFTER the htmlspecialchars so the entity isn't double- -// encoded. -echo "\n"; -echo "\n"; +echo "\n"; +echo "\n"; echo "\n"; if ($configs['aprsEnabled']) { - echo "\n"; + echo "\n"; } if ($configs['ircddbEnabled']) { - echo "\n"; + echo "\n"; } -// getActualLink() returns log-parsed strings (DMR talkgroups, -// D-Star reflector names, NXDN/M17 link state etc.) which can -// carry RF-controllable bytes; escape before display. -echo "\n"; +echo "\n"; echo "
".$lang['dstar_repeater']."
RPT1".str_replace(' ', ' ', htmlspecialchars((string)$configdstar['callsign'], ENT_QUOTES, 'UTF-8'))."
RPT2".str_replace(' ', ' ', htmlspecialchars((string)$configdstar['gateway'], ENT_QUOTES, 'UTF-8'))."
RPT1".str_replace(' ', ' ', $configdstar['callsign'])."
RPT2".str_replace(' ', ' ', $configdstar['gateway'])."
".$lang['dstar_net']."
APRS".htmlspecialchars(substr((string)$configs['aprsHostname'], 0, 16), ENT_QUOTES, 'UTF-8')."
APRS".substr($configs['aprsHostname'], 0, 16)."
IRC".htmlspecialchars(substr((string)$configs['ircddbHostname'], 0, 16), ENT_QUOTES, 'UTF-8')."
IRC".substr($configs['ircddbHostname'], 0 ,16)."
".htmlspecialchars((string)getActualLink($reverseLogLinesMMDVM, "D-Star"), ENT_QUOTES, 'UTF-8')."
".getActualLink($reverseLogLinesMMDVM, "D-Star")."
\n"; } $testMMDVModeDMR = getConfigItem("DMR", "Enable", $mmdvmconfigs); if ( $testMMDVModeDMR == 1 ) { //Hide the DMR information when DMR mode not enabled. -// DMR_Hosts.txt: read once via getDMRHostsLines() (functions.php) and -// cached for the request, so this scan and the YSF2DMR scan further -// down both iterate the same in-memory line array instead of two -// separate fopen/fgets passes over a 3-6K-line SD-card file. +$dmrMasterFile = fopen("/usr/local/etc/DMR_Hosts.txt", "r"); $dmrMasterHost = getConfigItem("DMR Network", "Address", $mmdvmconfigs); $dmrMasterPort = getConfigItem("DMR Network", "Port", $mmdvmconfigs); if ($dmrMasterHost == '127.0.0.1') { - if (isset($configdmrgateway['XLX Network 1']['Address'])) { $xlxMasterHost1 = $configdmrgateway['XLX Network 1']['Address']; } - else { $xlxMasterHost1 = ""; } - $dmrMasterHost1 = $configdmrgateway['DMR Network 1']['Address']; - $dmrMasterHost2 = $configdmrgateway['DMR Network 2']['Address']; - $dmrMasterHost3 = str_replace('_', ' ', $configdmrgateway['DMR Network 3']['Name']); - if (isset($configdmrgateway['DMR Network 4']['Name'])) {$dmrMasterHost4 = str_replace('_', ' ', $configdmrgateway['DMR Network 4']['Name']);} - if (isset($configdmrgateway['DMR Network 5']['Name'])) {$dmrMasterHost5 = str_replace('_', ' ', $configdmrgateway['DMR Network 5']['Name']);} - if (isset($configdmrgateway['DMR Network 6']['Name'])) {$dmrMasterHost6 = str_replace('_', ' ', $configdmrgateway['DMR Network 6']['Name']);} - foreach (getDMRHostsLines() as $dmrMasterLine) { + if (isset($configdmrgateway['XLX Network 1']['Address'])) { $xlxMasterHost1 = $configdmrgateway['XLX Network 1']['Address']; } + else { $xlxMasterHost1 = ""; } + $dmrMasterHost1 = $configdmrgateway['DMR Network 1']['Address']; + $dmrMasterHost2 = $configdmrgateway['DMR Network 2']['Address']; + $dmrMasterHost3 = str_replace('_', ' ', $configdmrgateway['DMR Network 3']['Name']); + if (isset($configdmrgateway['DMR Network 4']['Name'])) {$dmrMasterHost4 = str_replace('_', ' ', $configdmrgateway['DMR Network 4']['Name']);} + if (isset($configdmrgateway['DMR Network 5']['Name'])) {$dmrMasterHost5 = str_replace('_', ' ', $configdmrgateway['DMR Network 5']['Name']);} + if (isset($configdmrgateway['DMR Network 6']['Name'])) {$dmrMasterHost6 = str_replace('_', ' ', $configdmrgateway['DMR Network 6']['Name']);} + while (!feof($dmrMasterFile)) { + $dmrMasterLine = fgets($dmrMasterFile); $dmrMasterHostF = preg_split('/\s+/', $dmrMasterLine); - if ((count($dmrMasterHostF) >= 2) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { - if ((strpos($dmrMasterHostF[0], 'XLX_') === 0) && ($xlxMasterHost1 == $dmrMasterHostF[2])) { $xlxMasterHost1 = str_replace('_', ' ', $dmrMasterHostF[0]); } - if ((strpos($dmrMasterHostF[0], 'BM_') === 0) && ($dmrMasterHost1 == $dmrMasterHostF[2])) { $dmrMasterHost1 = str_replace('_', ' ', $dmrMasterHostF[0]); } - if ((strpos($dmrMasterHostF[0], 'DMR+_') === 0) && ($dmrMasterHost2 == $dmrMasterHostF[2])) { $dmrMasterHost2 = str_replace('_', ' ', $dmrMasterHostF[0]); } - } - } - if (strlen($xlxMasterHost1) > 19) { $xlxMasterHost1 = substr($xlxMasterHost1, 0, 17) . '..'; } - if (strlen($dmrMasterHost1) > 19) { $dmrMasterHost1 = substr($dmrMasterHost1, 0, 17) . '..'; } - if (strlen($dmrMasterHost2) > 19) { $dmrMasterHost2 = substr($dmrMasterHost2, 0, 17) . '..'; } - if (strlen($dmrMasterHost3) > 19) { $dmrMasterHost3 = substr($dmrMasterHost3, 0, 17) . '..'; } - if (isset($dmrMasterHost4)) { if (strlen($dmrMasterHost4) > 19) { $dmrMasterHost4 = substr($dmrMasterHost4, 0, 17) . '..'; } } - if (isset($dmrMasterHost5)) { if (strlen($dmrMasterHost5) > 19) { $dmrMasterHost5 = substr($dmrMasterHost5, 0, 17) . '..'; } } - if (isset($dmrMasterHost6)) { if (strlen($dmrMasterHost6) > 19) { $dmrMasterHost6 = substr($dmrMasterHost6, 0, 17) . '..'; } } + if ((count($dmrMasterHostF) >= 2) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { + if ((strpos($dmrMasterHostF[0], 'XLX_') === 0) && ($xlxMasterHost1 == $dmrMasterHostF[2])) { $xlxMasterHost1 = str_replace('_', ' ', $dmrMasterHostF[0]); } + if ((strpos($dmrMasterHostF[0], 'CDN_') === 0) && ($dmrMasterHost1 == $dmrMasterHostF[2])) { $dmrMasterHost1 = str_replace('_', ' ', $dmrMasterHostF[0]); } + if ((strpos($dmrMasterHostF[0], 'DMR+_') === 0) && ($dmrMasterHost2 == $dmrMasterHostF[2])) { $dmrMasterHost2 = str_replace('_', ' ', $dmrMasterHostF[0]); } + } + } + if (strlen($xlxMasterHost1) > 19) { $xlxMasterHost1 = substr($xlxMasterHost1, 0, 17) . '..'; } + if (strlen($dmrMasterHost1) > 19) { $dmrMasterHost1 = substr($dmrMasterHost1, 0, 17) . '..'; } + if (strlen($dmrMasterHost2) > 19) { $dmrMasterHost2 = substr($dmrMasterHost2, 0, 17) . '..'; } + if (strlen($dmrMasterHost3) > 19) { $dmrMasterHost3 = substr($dmrMasterHost3, 0, 17) . '..'; } + if (isset($dmrMasterHost4)) { if (strlen($dmrMasterHost4) > 19) { $dmrMasterHost4 = substr($dmrMasterHost4, 0, 17) . '..'; } } + if (isset($dmrMasterHost5)) { if (strlen($dmrMasterHost5) > 19) { $dmrMasterHost5 = substr($dmrMasterHost5, 0, 17) . '..'; } } + if (isset($dmrMasterHost6)) { if (strlen($dmrMasterHost6) > 19) { $dmrMasterHost6 = substr($dmrMasterHost6, 0, 17) . '..'; } } } else { - foreach (getDMRHostsLines() as $dmrMasterLine) { + while (!feof($dmrMasterFile)) { + $dmrMasterLine = fgets($dmrMasterFile); $dmrMasterHostF = preg_split('/\s+/', $dmrMasterLine); - if ((count($dmrMasterHostF) >= 4) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { - if (($dmrMasterHost == $dmrMasterHostF[2]) && ($dmrMasterPort == $dmrMasterHostF[4])) { $dmrMasterHost = str_replace('_', ' ', $dmrMasterHostF[0]); } - } - } - if (strlen($dmrMasterHost) > 19) { $dmrMasterHost = substr($dmrMasterHost, 0, 17) . '..'; } + if ((count($dmrMasterHostF) >= 4) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { + if (($dmrMasterHost == $dmrMasterHostF[2]) && ($dmrMasterPort == $dmrMasterHostF[4])) { $dmrMasterHost = str_replace('_', ' ', $dmrMasterHostF[0]); } + } + } + if (strlen($dmrMasterHost) > 19) { $dmrMasterHost = substr($dmrMasterHost, 0, 17) . '..'; } } +fclose($dmrMasterFile); echo "
\n"; echo "\n"; echo "\n"; -// All getConfigItem returns and $dmrMasterHost* values below -// originate from /etc/mmdvmhost or /etc/dmrgateway (parse_ini) -// or from log-parsed `exec(grep | awk)` pipelines. Escape every -// echoed value so an editor-injected payload (closes the read -// path of the M-3 stored XSS class) or a hostile log line can't -// break out of the table cell. -echo "\n"; -echo "\n"; +echo "\n"; +echo "\n"; echo ""; if (getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == 1) { echo "\n"; } else { echo "\n"; } echo ""; if (getConfigItem("DMR Network", "Slot2", $mmdvmconfigs) == 1) { echo "\n"; } else { echo "\n"; } echo "\n"; if (getEnabled("DMR Network", $mmdvmconfigs) == 1) { - if ($dmrMasterHost == '127.0.0.1') { - if ((isset($configdmrgateway['XLX Network 1']['Enabled'])) && ($configdmrgateway['XLX Network 1']['Enabled'] == 1)) { - echo "\n"; - } + if ($dmrMasterHost == '127.0.0.1') { + if ((isset($configdmrgateway['XLX Network 1']['Enabled'])) && ($configdmrgateway['XLX Network 1']['Enabled'] == 1)) { + echo "\n"; + } if ( !isset($configdmrgateway['XLX Network 1']['Enabled']) && isset($configdmrgateway['XLX Network']['Enabled']) && $configdmrgateway['XLX Network']['Enabled'] == 1) { - if (file_exists("/var/log/pi-star/DMRGateway-".gmdate("Y-m-d").".log")) { $xlxMasterHost1 = exec('grep \'XLX, Linking\|XLX, Unlinking\|XLX, Logged\' /var/log/pi-star/DMRGateway-'.gmdate("Y-m-d").'.log | tail -1 | awk \'{print $5 " " $8 " " $9}\''); } + if (file_exists("/var/log/pi-star/DMRGateway-".gmdate("Y-m-d").".log")) { $xlxMasterHost1 = exec('grep \'XLX, Linking\|XLX, Unlinking\|XLX, Logged\' /var/log/pi-star/DMRGateway-'.gmdate("Y-m-d").'.log | tail -1 | awk \'{print $5 " " $8 " " $9}\''); } else { $xlxMasterHost1 = exec('grep \'XLX, Linking\|XLX, Unlinking\|XLX, Logged\' /var/log/pi-star/DMRGateway-'.gmdate("Y-m-d", time() - 86340).'.log | tail -1 | awk \'{print $5 " " $8 " " $9}\''); } - if ( strpos($xlxMasterHost1, 'Linking') !== false ) { $xlxMasterHost1 = str_replace('Linking ', '', $xlxMasterHost1); } - else if ( strpos($xlxMasterHost1, 'Unlinking') !== false ) { $xlxMasterHost1 = "XLX Not Linked"; } - else if ( strpos($xlxMasterHost1, 'Logged') !== false ) { $xlxMasterHost1 = "XLX Not Linked"; } - echo "\n"; + if ( strpos($xlxMasterHost1, 'Linking') !== false ) { $xlxMasterHost1 = str_replace('Linking ', '', $xlxMasterHost1); } + else if ( strpos($xlxMasterHost1, 'Unlinking') !== false ) { $xlxMasterHost1 = "XLX Not Linked"; } + else if ( strpos($xlxMasterHost1, 'Logged') !== false ) { $xlxMasterHost1 = "XLX Not Linked"; } + echo "\n"; } - if ($configdmrgateway['DMR Network 1']['Enabled'] == 1) { - echo "\n"; - } - if ($configdmrgateway['DMR Network 2']['Enabled'] == 1) { - echo "\n"; - } - if ($configdmrgateway['DMR Network 3']['Enabled'] == 1) { - echo "\n"; - } - if (isset($configdmrgateway['DMR Network 4']['Enabled'])) { - if ($configdmrgateway['DMR Network 4']['Enabled'] == 1) { - echo "\n"; - } - } - if (isset($configdmrgateway['DMR Network 5']['Enabled'])) { - if ($configdmrgateway['DMR Network 5']['Enabled'] == 1) { - echo "\n"; - } - } - if (isset($configdmrgateway['DMR Network 6']['Enabled'])) { - if ($configdmrgateway['DMR Network 6']['Enabled'] == 1) { - echo "\n"; - } - } - } - else { - echo "\n"; - } - } - else { - echo "\n"; - } + if ($configdmrgateway['DMR Network 1']['Enabled'] == 1) { + echo "\n"; + } + if ($configdmrgateway['DMR Network 2']['Enabled'] == 1) { + echo "\n"; + } + if ($configdmrgateway['DMR Network 3']['Enabled'] == 1) { + echo "\n"; + } + if (isset($configdmrgateway['DMR Network 4']['Enabled'])) { + if ($configdmrgateway['DMR Network 4']['Enabled'] == 1) { + echo "\n"; + } + } + if (isset($configdmrgateway['DMR Network 5']['Enabled'])) { + if ($configdmrgateway['DMR Network 5']['Enabled'] == 1) { + echo "\n"; + } + } + if (isset($configdmrgateway['DMR Network 6']['Enabled'])) { + if ($configdmrgateway['DMR Network 6']['Enabled'] == 1) { + echo "\n"; + } + } + } + else { + echo "\n"; + } + } + else { + echo "\n"; + } echo "
".$lang['dmr_repeater']."
DMR ID".htmlspecialchars((string)getConfigItem("General", "Id", $mmdvmconfigs), ENT_QUOTES, 'UTF-8')."
DMR CC".htmlspecialchars((string)getConfigItem("DMR", "ColorCode", $mmdvmconfigs), ENT_QUOTES, 'UTF-8')."
DMR ID".getConfigItem("General", "Id", $mmdvmconfigs)."
DMR CC".getConfigItem("DMR", "ColorCode", $mmdvmconfigs)."
TS1enabled
disabled
TS2enabled
disabled
".$lang['dmr_master']."
".htmlspecialchars((string)$xlxMasterHost1, ENT_QUOTES, 'UTF-8')."
".$xlxMasterHost1."
".htmlspecialchars((string)$xlxMasterHost1, ENT_QUOTES, 'UTF-8')."
".$xlxMasterHost1."
".htmlspecialchars((string)$dmrMasterHost1, ENT_QUOTES, 'UTF-8')."
".htmlspecialchars((string)$dmrMasterHost2, ENT_QUOTES, 'UTF-8')."
".htmlspecialchars((string)$dmrMasterHost3, ENT_QUOTES, 'UTF-8')."
".htmlspecialchars((string)$dmrMasterHost4, ENT_QUOTES, 'UTF-8')."
".htmlspecialchars((string)$dmrMasterHost5, ENT_QUOTES, 'UTF-8')."
".htmlspecialchars((string)$dmrMasterHost6, ENT_QUOTES, 'UTF-8')."
".htmlspecialchars((string)$dmrMasterHost, ENT_QUOTES, 'UTF-8')."
No DMR Network
".$dmrMasterHost1."
".$dmrMasterHost2."
".$dmrMasterHost3."
".$dmrMasterHost4."
".$dmrMasterHost5."
".$dmrMasterHost6."
".$dmrMasterHost."
No DMR Network
\n"; } @@ -378,99 +314,100 @@ if ( $testMMDVModeYSF == 1 || $testDMR2YSF ) { //Hide the YSF information when S echo "
\n"; echo "\n"; echo "\n"; - echo "\n"; + echo "\n"; echo "
".$lang['ysf_net']."
".htmlspecialchars((string)$ysfLinkedToTxt, ENT_QUOTES, 'UTF-8')."
".$ysfLinkedToTxt."
\n"; } if ( isset($configysf2dmr['Enabled']['Enabled']) ) { $testYSF2DMR = $configysf2dmr['Enabled']['Enabled']; } if ( $testYSF2DMR ) { //Hide the YSF2DMR information when YSF2DMR Network mode not enabled. - // Reuses the in-memory DMR_Hosts.txt line array cached by - // getDMRHostsLines() — same data the DMR block above just - // walked, no second SD-card read. + $dmrMasterFile = fopen("/usr/local/etc/DMR_Hosts.txt", "r"); $dmrMasterHost = $configysf2dmr['DMR Network']['Address']; - foreach (getDMRHostsLines() as $dmrMasterLine) { + while (!feof($dmrMasterFile)) { + $dmrMasterLine = fgets($dmrMasterFile); $dmrMasterHostF = preg_split('/\s+/', $dmrMasterLine); - if ((count($dmrMasterHostF) >= 2) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { + if ((count($dmrMasterHostF) >= 2) && (strpos($dmrMasterHostF[0], '#') === FALSE) && ($dmrMasterHostF[0] != '')) { if ($dmrMasterHost == $dmrMasterHostF[2]) { $dmrMasterHost = str_replace('_', ' ', $dmrMasterHostF[0]); } } } if (strlen($dmrMasterHost) > 19) { $dmrMasterHost = substr($dmrMasterHost, 0, 17) . '..'; } + fclose($dmrMasterFile); echo "
\n"; echo "\n"; echo "\n"; - echo "\n"; - echo "\n"; - echo "\n"; + echo "\n"; + echo "\n"; + echo "\n"; echo "
YSF2DMR
DMR ID".htmlspecialchars((string)$configysf2dmr['DMR Network']['Id'], ENT_QUOTES, 'UTF-8')."
YSF2".$lang['dmr_master']."
".htmlspecialchars((string)$dmrMasterHost, ENT_QUOTES, 'UTF-8')."
DMR ID".$configysf2dmr['DMR Network']['Id']."
YSF2".$lang['dmr_master']."
".$dmrMasterHost."
\n"; } $testMMDVModeP25 = getConfigItem("P25 Network", "Enable", $mmdvmconfigs); if ( isset($configysf2p25['Enabled']['Enabled']) ) { $testYSF2P25 = $configysf2p25['Enabled']['Enabled']; } if ( $testMMDVModeP25 == 1 || $testYSF2P25 ) { //Hide the P25 information when P25 Network mode not enabled. - echo "
\n"; - echo "\n"; - if (getConfigItem("P25", "NAC", $mmdvmconfigs)) { - echo "\n"; - echo "\n"; - } else { - echo "\n"; - echo "\n"; - } - echo "\n"; - echo "\n"; - echo "
".$lang['p25_radio']."
NAC".htmlspecialchars((string)getConfigItem("P25", "NAC", $mmdvmconfigs), ENT_QUOTES, 'UTF-8')."
".$lang['p25_radio']."
NAC0
".$lang['p25_net']."
".htmlspecialchars((string)getActualLink($logLinesP25Gateway, "P25"), ENT_QUOTES, 'UTF-8')."
\n"; + echo "
\n"; + echo "\n"; + if (getConfigItem("P25", "NAC", $mmdvmconfigs)) { + echo "\n"; + echo "\n"; + } else { + echo "\n"; + echo "\n"; + } + echo "\n"; + echo "\n"; + echo "
".$lang['p25_radio']."
NAC".getConfigItem("P25", "NAC", $mmdvmconfigs)."
".$lang['p25_radio']."
NAC0
".$lang['p25_net']."
".getActualLink($logLinesP25Gateway, "P25")."
\n"; } $testMMDVModeNXDN = getConfigItem("NXDN Network", "Enable", $mmdvmconfigs); if ( isset($configysf2nxdn['Enabled']['Enabled']) ) { if ($configysf2nxdn['Enabled']['Enabled'] == 1) { $testYSF2NXDN = 1; } } if ( isset($configdmr2nxdn['Enabled']['Enabled']) ) { if ($configdmr2nxdn['Enabled']['Enabled'] == 1) { $testDMR2NXDN = 1; } } if ( $testMMDVModeNXDN == 1 || isset($testYSF2NXDN) || isset($testDMR2NXDN) ) { //Hide the NXDN information when NXDN Network mode not enabled. - echo "
\n"; - echo "\n"; - if (getConfigItem("NXDN", "RAN", $mmdvmconfigs)) { - echo "\n"; - echo "\n"; - } else { - echo "\n"; - echo "\n"; - } - echo "\n"; - if (file_exists('/etc/nxdngateway')) { - echo "\n"; - } else { - echo "\n"; - } - echo "
".$lang['nxdn_radio']."
RAN".htmlspecialchars((string)getConfigItem("NXDN", "RAN", $mmdvmconfigs), ENT_QUOTES, 'UTF-8')."
".$lang['nxdn_radio']."
RAN0
".$lang['nxdn_net']."
".htmlspecialchars((string)getActualLink($logLinesNXDNGateway, "NXDN"), ENT_QUOTES, 'UTF-8')."
TG 65000
\n"; + echo "
\n"; + echo "\n"; + if (getConfigItem("NXDN", "RAN", $mmdvmconfigs)) { + echo "\n"; + echo "\n"; + } else { + echo "\n"; + echo "\n"; + } + echo "\n"; + if (file_exists('/etc/nxdngateway')) { + echo "\n"; + } else { + echo "\n"; + } + echo "
".$lang['nxdn_radio']."
RAN".getConfigItem("NXDN", "RAN", $mmdvmconfigs)."
".$lang['nxdn_radio']."
RAN0
".$lang['nxdn_net']."
".getActualLink($logLinesNXDNGateway, "NXDN")."
TG 65000
\n"; } $testMMDVModeM17 = getConfigItem("M17 Network", "Enable", $mmdvmconfigs); if ( $testMMDVModeM17 == 1 ) { //Hide the M17 information when P25 Network mode not enabled. - echo "
\n"; - echo "\n"; - if (getConfigItem("M17", "CAN", $mmdvmconfigs)) { - echo "\n"; - echo "\n"; - } else { - echo "\n"; - echo "\n"; - } - echo "\n"; - echo "\n"; - echo "
".$lang['m17_radio']."
CAN".htmlspecialchars((string)getConfigItem("M17", "CAN", $mmdvmconfigs), ENT_QUOTES, 'UTF-8')."
".$lang['m17_radio']."
CAN0
".$lang['m17_net']."
".htmlspecialchars((string)getActualLink($logLinesM17Gateway, "M17"), ENT_QUOTES, 'UTF-8')."
\n"; + echo "
\n"; + echo "\n"; + if (getConfigItem("M17", "CAN", $mmdvmconfigs)) { + echo "\n"; + echo "\n"; + } else { + echo "\n"; + echo "\n"; + } + echo "\n"; + echo "\n"; + echo "
".$lang['m17_radio']."
CAN".getConfigItem("M17", "CAN", $mmdvmconfigs)."
".$lang['m17_radio']."
CAN0
".$lang['m17_net']."
".getActualLink($logLinesM17Gateway, "M17")."
\n"; } $testMMDVModePOCSAG = getConfigItem("POCSAG Network", "Enable", $mmdvmconfigs); if ( $testMMDVModePOCSAG == 1 ) { //Hide the POCSAG information when POCSAG Network mode not enabled. - echo "
\n"; - echo "\n"; - echo "\n"; - echo "\n"; - if (isset($configdapnetgateway['DAPNET']['Address'])) { - $dapnetGatewayRemoteAddr = $configdapnetgateway['DAPNET']['Address']; - if (strlen($dapnetGatewayRemoteAddr) > 19) { $dapnetGatewayRemoteAddr = substr($dapnetGatewayRemoteAddr, 0, 17) . '..'; } - echo "\n"; - echo "\n"; - } - echo "
POCSAG
Tx".htmlspecialchars((string)getMHZ(getConfigItem("POCSAG", "Frequency", $mmdvmconfigs)), ENT_QUOTES, 'UTF-8')."
POCSAG Master
".htmlspecialchars((string)$dapnetGatewayRemoteAddr, ENT_QUOTES, 'UTF-8')."
\n"; + echo "
\n"; + echo "\n"; + echo "\n"; + echo "\n"; + if (isset($configdapnetgateway['DAPNET']['Address'])) { + $dapnetGatewayRemoteAddr = $configdapnetgateway['DAPNET']['Address']; + if (strlen($dapnetGatewayRemoteAddr) > 19) { $dapnetGatewayRemoteAddr = substr($dapnetGatewayRemoteAddr, 0, 17) . '..'; } + echo "\n"; + echo "\n"; + } + echo "
POCSAG
Tx".getMHZ(getConfigItem("POCSAG", "Frequency", $mmdvmconfigs))."
POCSAG Master
".$dapnetGatewayRemoteAddr."
\n"; } +?> diff --git a/mmdvmhost/tgif_links.php b/mmdvmhost/tgif_links.php new file mode 100644 index 0000000..ecf2d26 --- /dev/null +++ b/mmdvmhost/tgif_links.php @@ -0,0 +1,96 @@ +array('timeout' => 2, 'header' => 'User-Agent: Pi-Star Dashboard for '.$dmrID) )); // Add Timout and User Agent to include DMRID + $json_data = file_get_contents("http://tgif.network:5040/api/sessions", false, $jsonContext); + $json = json_decode($json_data, false); + + // Work out what session number we are using + foreach($json as $key => $jsons) { + foreach($jsons as $key => $value) { + if ($json->sessions[$key]->repeater_id == $dmrID) { $session_nr = $key; } + } + } + + // Pull the information from JSON + if (isset($session_nr)) { + $repeaterid = $json->sessions[$session_nr]->repeater_id; + if ($json->sessions[$session_nr]->tg0 == "4000") { $slot1tg = "None"; } else { $slot1tg = "TG".$json->sessions[$session_nr]->tg0; } + if ($json->sessions[$session_nr]->tg == "4000") { $slot2tg = "None"; } else { $slot2tg = "TG".$json->sessions[$session_nr]->tg; } + + echo 'Active TGIF Connections + + + + + + + '."\n"; + + echo ' '."\n"; + echo ' '; + echo ''; + echo ''; + echo ''; + echo ''."\n"; + echo '
DMR MasterConnected MasterRepeater IDThe ID for this Repeater/HotspotSlot1 TGTG linked to Slot 1Slot2 TGTG linked to Slot 2
tgif.network'.$repeaterid.''.$slot1tg.''.$slot2tg.'
'."\n"; + echo '
'."\n"; + } +} +?> diff --git a/mmdvmhost/tgif_manager.php b/mmdvmhost/tgif_manager.php index 87868a8..70e571b 100644 --- a/mmdvmhost/tgif_manager.php +++ b/mmdvmhost/tgif_manager.php @@ -1,192 +1,165 @@ 'Continue', - '101' => 'Switching Protocols', - '200' => 'OK', - '201' => 'Created', - '202' => 'Accepted', - '203' => 'Non-Authoritative Information', - '204' => 'No Content', - '205' => 'Reset Content', - '206' => 'Partial Content', - '300' => 'Multiple Choices', - '302' => 'Found', - '303' => 'See Other', - '304' => 'Not Modified', - '305' => 'Use Proxy', - '400' => 'Bad Request', - '401' => 'Unauthorized', - '402' => 'Payment Required', - '403' => 'Forbidden', - '404' => 'Not Found', - '405' => 'Method Not Allowed', - '406' => 'Not Acceptable', - '407' => 'Proxy Authentication Required', - '408' => 'Request Timeout', - '409' => 'Conflict', - '410' => 'Gone', - '411' => 'Length Required', - '412' => 'Precondition Failed', - '413' => 'Request Entity Too Large', - '414' => 'Request-URI Too Long', - '415' => 'Unsupported Media Type', - '416' => 'Requested Range Not Satisfiable', - '417' => 'Expectation Failed', - '500' => 'Internal Server Error', - '501' => 'Not Implemented', - '502' => 'Bad Gateway', - '503' => 'Service Unavailable', - '504' => 'Gateway Timeout', - '505' => 'HTTP Version Not Supported' - ); - // Caste the status code to a string. - $code = preg_replace("/[^0-9]/", "", $code); - $code = (string)$code; - // Determine if it exists in the array. - if(array_key_exists($code, $statuslist) ) { - // Return the status text - return $statuslist[$code]; - } else { - // If it doesn't exists, degrade by returning the code. - return $code; - } - } + function httpStatusText($code = 0) { + // List of HTTP status codes. + $statuslist = array( + '100' => 'Continue', + '101' => 'Switching Protocols', + '200' => 'OK', + '201' => 'Created', + '202' => 'Accepted', + '203' => 'Non-Authoritative Information', + '204' => 'No Content', + '205' => 'Reset Content', + '206' => 'Partial Content', + '300' => 'Multiple Choices', + '302' => 'Found', + '303' => 'See Other', + '304' => 'Not Modified', + '305' => 'Use Proxy', + '400' => 'Bad Request', + '401' => 'Unauthorized', + '402' => 'Payment Required', + '403' => 'Forbidden', + '404' => 'Not Found', + '405' => 'Method Not Allowed', + '406' => 'Not Acceptable', + '407' => 'Proxy Authentication Required', + '408' => 'Request Timeout', + '409' => 'Conflict', + '410' => 'Gone', + '411' => 'Length Required', + '412' => 'Precondition Failed', + '413' => 'Request Entity Too Large', + '414' => 'Request-URI Too Long', + '415' => 'Unsupported Media Type', + '416' => 'Requested Range Not Satisfiable', + '417' => 'Expectation Failed', + '500' => 'Internal Server Error', + '501' => 'Not Implemented', + '502' => 'Bad Gateway', + '503' => 'Service Unavailable', + '504' => 'Gateway Timeout', + '505' => 'HTTP Version Not Supported' + ); + // Caste the status code to a string. + $code = preg_replace("/[^0-9]/", "", $code); + $code = (string)$code; + // Determine if it exists in the array. + if(array_key_exists($code, $statuslist) ) { + // Return the status text + return $statuslist[$code]; + } else { + // If it doesn't exists, degrade by returning the code. + return $code; + } + } - // Set some Variable - $dmrID = ""; + // Set some Variable + $dmrID = ""; - // Check if DMR is Enabled - $testMMDVModeDMR = getConfigItem("DMR", "Enable", $mmdvmconfigs); + // Check if DMR is Enabled + $testMMDVModeDMR = getConfigItem("DMR", "Enable", $mmdvmconfigs); - if ( $testMMDVModeDMR == 1 ) { - //Load the dmrgateway config file - $dmrGatewayConfigFile = '/etc/dmrgateway'; - if (fopen($dmrGatewayConfigFile,'r')) { $configdmrgateway = parse_ini_file($dmrGatewayConfigFile, true); } + if ( $testMMDVModeDMR == 1 ) { + //Load the dmrgateway config file + $dmrGatewayConfigFile = '/etc/dmrgateway'; + if (fopen($dmrGatewayConfigFile,'r')) { $configdmrgateway = parse_ini_file($dmrGatewayConfigFile, true); } - // Get the current DMR Master from the config - $dmrMasterHost = getConfigItem("DMR Network", "Address", $mmdvmconfigs); - if ( $dmrMasterHost == '127.0.0.1' ) { - // DMRGateway, need to check each config - if (isset($configdmrgateway['DMR Network 1']['Address'])) { - if (($configdmrgateway['DMR Network 1']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 1']['Enabled'])) { - $dmrID = $configdmrgateway['DMR Network 1']['Id']; - } - } - if (isset($configdmrgateway['DMR Network 2']['Address'])) { - if (($configdmrgateway['DMR Network 2']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 2']['Enabled'])) { - $dmrID = $configdmrgateway['DMR Network 2']['Id']; - } - } - if (isset($configdmrgateway['DMR Network 3']['Address'])) { - if (($configdmrgateway['DMR Network 3']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 3']['Enabled'])) { - $dmrID = $configdmrgateway['DMR Network 3']['Id']; - } - } - if (isset($configdmrgateway['DMR Network 4']['Address'])) { - if (($configdmrgateway['DMR Network 4']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 4']['Enabled'])) { - $dmrID = $configdmrgateway['DMR Network 4']['Id']; - } - } - if (isset($configdmrgateway['DMR Network 5']['Address'])) { - if (($configdmrgateway['DMR Network 5']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 5']['Enabled'])) { - $dmrID = $configdmrgateway['DMR Network 5']['Id']; - } - } - } else if ( $dmrMasterHost == 'tgif.network' ) { - // MMDVMHost Connected directly to TGIF, get the ID form here - if (getConfigItem("DMR", "Id", $mmdvmconfigs)) { - $dmrID = getConfigItem("DMR", "Id", $mmdvmconfigs); - } else { - $dmrID = getConfigItem("General", "Id", $mmdvmconfigs); - } - } - } + // Get the current DMR Master from the config + $dmrMasterHost = getConfigItem("DMR Network", "Address", $mmdvmconfigs); + if ( $dmrMasterHost == '127.0.0.1' ) { + // DMRGateway, need to check each config + if (isset($configdmrgateway['DMR Network 1']['Address'])) { + if (($configdmrgateway['DMR Network 1']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 1']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 1']['Id']; + } + } + if (isset($configdmrgateway['DMR Network 2']['Address'])) { + if (($configdmrgateway['DMR Network 2']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 2']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 2']['Id']; + } + } + if (isset($configdmrgateway['DMR Network 3']['Address'])) { + if (($configdmrgateway['DMR Network 3']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 3']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 3']['Id']; + } + } + if (isset($configdmrgateway['DMR Network 4']['Address'])) { + if (($configdmrgateway['DMR Network 4']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 4']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 4']['Id']; + } + } + if (isset($configdmrgateway['DMR Network 5']['Address'])) { + if (($configdmrgateway['DMR Network 5']['Address'] == "tgif.network") && ($configdmrgateway['DMR Network 5']['Enabled'])) { + $dmrID = $configdmrgateway['DMR Network 5']['Id']; + } + } + } else if ( $dmrMasterHost == 'tgif.network' ) { + // MMDVMHost Connected directly to TGIF, get the ID form here + if (getConfigItem("DMR", "Id", $mmdvmconfigs)) { + $dmrID = getConfigItem("DMR", "Id", $mmdvmconfigs); + } else { + $dmrID = getConfigItem("General", "Id", $mmdvmconfigs); + } + } + } - if ( $dmrID ) { - // Work out if the data has been posted or not - if ( !empty($_POST) && isset($_POST["tgifSubmit"]) ): // Data has been posted for this page - // Are we a repeater - if ( getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" ) { - $targetSlot = "1"; - } else { - $targetSlot = preg_replace("/[^0-9]/", "", $_POST["tgifSlot"]); - $targetSlot--; - } - // Figure out what has been posted - if ( (isset($_POST["tgifNumber"])) && (isset($_POST["tgifSubmit"])) ) { - $targetTG = preg_replace("/[^0-9]/", "", $_POST["tgifNumber"]); - if ($targetTG < 1) { $targetTG = "4000"; } - } else { - $targetTG = "4000"; - } - if ($_POST["tgifAction"] == "UNLINK") { $targetTG = "4000"; } - // Perform the GET request - $tgifApiUrl = "http://tgif.network:5040/api/sessions/update/".$dmrID."/".$targetSlot."/".$targetTG; - $result = file_get_contents($tgifApiUrl); - // Output to the browser - echo 'TGIF Manager'."\n"; - echo "\n\n\n
Command Output
"; - //echo "Sending command to TGIF API"; - echo "TGIF API: "; - echo httpStatusText($result); - echo "
\n"; - echo "
\n"; - // Clean up... - unset($_POST); - echo ''; - else: // Do this when we are not handling post data - echo 'TGIF Manager'."\n"; - echo '
'."\n"; - echo csrf_field_html()."\n"; - echo ' - - - - - - - - - - - - -
Talkgroup NumberEnter the Talkgroup numberSlotWhere to link/unlinkLink / UnlinkLink or unlinkActionTake Action
TS1 TS2Link UnLink

'."\n"; - endif; - } + if ( $dmrID ) { + // Work out if the data has been posted or not + if ( !empty($_POST) && isset($_POST["tgifSubmit"]) ): // Data has been posted for this page + // Are we a repeater + if ( getConfigItem("DMR Network", "Slot1", $mmdvmconfigs) == "0" ) { + $targetSlot = "1"; + } else { + $targetSlot = preg_replace("/[^0-9]/", "", $_POST["tgifSlot"]); + $targetSlot--; + } + // Figure out what has been posted + if ( (isset($_POST["tgifNumber"])) && (isset($_POST["tgifSubmit"])) ) { + $targetTG = preg_replace("/[^0-9]/", "", $_POST["tgifNumber"]); + if ($targetTG < 1) { $targetTG = "4000"; } + } else { + $targetTG = "4000"; + } + if ($_POST["tgifAction"] == "UNLINK") { $targetTG = "4000"; } + // Perform the GET request + $tgifApiUrl = "http://tgif.network:5040/api/sessions/update/".$dmrID."/".$targetSlot."/".$targetTG; + $result = file_get_contents($tgifApiUrl); + // Output to the browser + echo 'TGIF Manager'."\n"; + echo "\n\n\n
Command Output
"; + //echo "Sending command to TGIF API"; + echo "TGIF API: "; + echo httpStatusText($result); + echo "
\n"; + echo "
\n"; + // Clean up... + unset($_POST); + echo ''; + else: // Do this when we are not handling post data + echo 'TGIF Manager'."\n"; + echo ''."\n"; + echo ' + + + + + + + + + + + + +
Talkgroup NumberEnter the Talkgroup numberSlotWhere to link/unlinkLink / UnlinkLink or unlinkActionTake Action
TS1 TS2Link UnLink

'."\n"; + endif; + } } +?> diff --git a/mmdvmhost/tools.php b/mmdvmhost/tools.php index 7050b9f..20121e6 100644 --- a/mmdvmhost/tools.php +++ b/mmdvmhost/tools.php @@ -1,73 +1,39 @@ 0) { - $uptimeString .= $days; - $uptimeString .= (($days == 1) ? " day" : " days"); - } - if ($hours > 0) { - $uptimeString .= (($days > 0) ? ", " : "") . $hours; - $uptimeString .= (($hours == 1) ? " hr" : " hrs"); - } - if ($mins > 0) { - $uptimeString .= (($days > 0 || $hours > 0) ? ", " : "") . $mins; - $uptimeString .= (($mins == 1) ? " min" : " mins"); - } - if ($secs > 0) { - $uptimeString .= (($days > 0 || $hours > 0 || $mins > 0) ? ", " : "") . $secs; - $uptimeString .= (($secs == 1) ? " s" : " s"); - } - return $uptimeString; + if ($days > 0) { + $uptimeString .= $days; + $uptimeString .= (($days == 1) ? " day" : " days"); + } + if ($hours > 0) { + $uptimeString .= (($days > 0) ? ", " : "") . $hours; + $uptimeString .= (($hours == 1) ? " hr" : " hrs"); + } + if ($mins > 0) { + $uptimeString .= (($days > 0 || $hours > 0) ? ", " : "") . $mins; + $uptimeString .= (($mins == 1) ? " min" : " mins"); + } + if ($secs > 0) { + $uptimeString .= (($days > 0 || $hours > 0 || $mins > 0) ? ", " : "") . $secs; + $uptimeString .= (($secs == 1) ? " s" : " s"); + } + return $uptimeString; } -function startsWith($haystack, $needle) -{ +function startsWith($haystack, $needle) { return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== false; } -function getMHZ($freq) -{ - return substr($freq,0,3) . "." . substr($freq,3,6) . " MHz"; +function getMHZ($freq) { + return substr($freq,0,3) . "." . substr($freq,3,6) . " MHz"; } -function isProcessRunning($processName, $full = false, $refresh = false) -{ +function isProcessRunning($processName, $full = false, $refresh = false) { if ($full) { static $processes_full = array(); if ($refresh) $processes_full = array(); @@ -86,44 +52,42 @@ function isProcessRunning($processName, $full = false, $refresh = false) return false; } -function createConfigLines() -{ - $out =""; - foreach($_GET as $key=>$val) { - if($key != "cmd") { - $out .= "define(\"$key\", \"$val\");"."\n"; - } - } - return $out; +function createConfigLines() { + $out =""; + foreach($_GET as $key=>$val) { + if($key != "cmd") { + $out .= "define(\"$key\", \"$val\");"."\n"; + } + } + return $out; +} + +function getSize($filesize, $precision = 2) { + $units = array('', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'); + foreach ($units as $idUnit => $unit) { + if ($filesize > 1024) + $filesize /= 1024; + else + break; + } + return round($filesize, $precision).' '.$units[$idUnit].'B'; } -function getSize($filesize, $precision = 2) -{ - $units = array('', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'); - foreach ($units as $idUnit => $unit) { - if ($filesize > 1024) - $filesize /= 1024; - else - break; - } - return round($filesize, $precision).' '.$units[$idUnit].'B'; -} - -function checkSetup() -{ - $el = error_reporting(); - error_reporting(E_ERROR | E_WARNING | E_PARSE); - if (defined(DISTRIBUTION)) { +function checkSetup() { + $el = error_reporting(); + error_reporting(E_ERROR | E_WARNING | E_PARSE); + if (defined(DISTRIBUTION)) { ?> - - + + diff --git a/mmdvmhost/ysf_manager.php b/mmdvmhost/ysf_manager.php index 5db51d9..96af8ce 100644 --- a/mmdvmhost/ysf_manager.php +++ b/mmdvmhost/ysf_manager.php @@ -1,166 +1,139 @@ Link|UnLink - * ` against the YSFGateway remote-control port configured in - * /etc/ysfgateway. Triggers a 2 s `setTimeout` reload. - * - * Inputs: - * /etc/ysfgateway Gateway config + remote port. Remote - * Commands must be enabled there for - * this form to do anything. - * /usr/local/etc/YSFHosts.txt Reflector picklist. - * /usr/local/etc/FCSHosts.txt Optional FCS rooms picklist. - * - * NOTE for the security pass: validation is whitelist-regex; no - * setEmbeddableSecurityHeaders() call in this file. Coverage gap. - */ - if ($_SERVER["PHP_SELF"] == "/admin/index.php") { // Stop this working outside of the admin page - include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config - include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools - include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDash Functions - include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code + include_once $_SERVER['DOCUMENT_ROOT'].'/config/config.php'; // MMDVMDash Config + include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/tools.php'; // MMDVMDash Tools + include_once $_SERVER['DOCUMENT_ROOT'].'/mmdvmhost/functions.php'; // MMDVMDash Functions + include_once $_SERVER['DOCUMENT_ROOT'].'/config/language.php'; // Translation Code - // Check if YSF is Enabled - $testMMDVModeYSF = getConfigItem("System Fusion Network", "Enable", $mmdvmconfigs); - if ( $testMMDVModeYSF == 1 ) { + // Check if YSF is Enabled + $testMMDVModeYSF = getConfigItem("System Fusion Network", "Enable", $mmdvmconfigs); + if ( $testMMDVModeYSF == 1 ) { - //Load the ysfgateway config file - $ysfGatewayConfigFile = '/etc/ysfgateway'; - if (fopen($ysfGatewayConfigFile,'r')) { $configysfgateway = parse_ini_file($ysfGatewayConfigFile, true); } + //Load the ysfgateway config file + $ysfGatewayConfigFile = '/etc/ysfgateway'; + if (fopen($ysfGatewayConfigFile,'r')) { $configysfgateway = parse_ini_file($ysfGatewayConfigFile, true); } - // Check that the remote is enabled - if ( $configysfgateway['Remote Commands']['Enable'] == 1 ) { - $remotePort = $configysfgateway['Remote Commands']['Port']; - if (!empty($_POST) && isset($_POST["ysfMgrSubmit"])) { - // Handle Posted Data - if (preg_match('/[^A-Za-z0-9]/',$_POST['ysfLinkHost'])) { unset ($_POST['ysfLinkHost']);} - if ($_POST["Link"] == "LINK") { - if ($_POST['ysfLinkHost'] == "none") { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." UnLink"; - } else { - $formattedLinkTarget = preg_replace('/([a-zA-Z]+)([0-9]+)/', '$1 $2', $_POST['ysfLinkHost']); - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." Link".$formattedLinkTarget; - } - } elseif ($_POST["Link"] == "UNLINK") { - $remoteCommand = "cd /var/log/pi-star && sudo /usr/local/bin/RemoteCommand ".$remotePort." UnLink"; - } else { - echo "YSF Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; - echo "
\n
\n"; - unset($_POST); - echo ''; - } - if (empty($_POST['ysfLinkHost'])) { - echo "YSF Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo "Somthing wrong with your input, (No target specified) - please try again"; - echo "
\n
\n"; - unset($_POST); - echo ''; - } - if (isset($remoteCommand)) { - echo "YSF Link Manager\n"; - echo "\n\n\n
Command Output
"; - echo htmlspecialchars((string)exec($remoteCommand), ENT_QUOTES, 'UTF-8'); - echo "
\n
\n"; - echo ''; - } - } else { - // Output HTML - ?> - YSF Link Manager - - - - - - - - - - - - - -
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
- - Link - UnLink - - -
- -
- YSF Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (Neither Link nor Unlink Sent) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (empty($_POST['ysfLinkHost'])) { + echo "YSF Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo "Somthing wrong with your input, (No target specified) - please try again"; + echo "
\n
\n"; + unset($_POST); + echo ''; + } + if (isset($remoteCommand)) { + echo "YSF Link Manager\n"; + echo "\n\n\n
Command Output
"; + echo exec($remoteCommand); + echo "
\n
\n"; + echo ''; + } + } else { + // Output HTML + ?> + YSF Link Manager +
+ + + + + + + + + + + +
ReflectorReflectorLink / Un-LinkLink / Un-LinkActionAction
+ + Link + UnLink + + +
+
+
+