mirror of
https://github.com/RaspAP/raspap-webgui.git
synced 2025-04-21 19:23:25 +00:00
Compare commits
166 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c3175459ab | ||
![]() |
3bf682d752 | ||
![]() |
9e0801aa0c | ||
![]() |
a21b0a8f99 | ||
![]() |
5f1b16bc74 | ||
![]() |
deba5e1e74 | ||
![]() |
0960e8bac9 | ||
![]() |
4a4506a913 | ||
![]() |
bfab3d7441 | ||
![]() |
47d7c121de | ||
![]() |
484b89718a | ||
![]() |
d6c8ac32a7 | ||
![]() |
3d6b4e1f15 | ||
![]() |
8d482845b0 | ||
![]() |
a1550d8049 | ||
![]() |
5584e3b72c | ||
![]() |
b0ba029c66 | ||
![]() |
48e492bf10 | ||
![]() |
821ac9c1f8 | ||
![]() |
49cb3911b8 | ||
![]() |
8ad582b3b2 | ||
![]() |
bbf1caf777 | ||
![]() |
b3c6178274 | ||
![]() |
a5907d8f7f | ||
![]() |
8569c2b4d5 | ||
![]() |
2a70f6ee11 | ||
![]() |
c8b0408bd5 | ||
![]() |
125ae7a39a | ||
![]() |
20fe5fc5a7 | ||
![]() |
168ed2448f | ||
![]() |
a2b8dfe551 | ||
![]() |
4aee1e49d9 | ||
![]() |
16d92bb486 | ||
![]() |
de376d04d1 | ||
![]() |
d730c174d4 | ||
![]() |
c798f5fd69 | ||
![]() |
3a73916206 | ||
![]() |
f46be0139e | ||
![]() |
a6295aef6e | ||
![]() |
556c2be855 | ||
![]() |
80e8178384 | ||
![]() |
b1c429f404 | ||
![]() |
f0b992b9be | ||
![]() |
084b2e1268 | ||
![]() |
0fd60e3730 | ||
![]() |
cfc6644087 | ||
![]() |
2cd4abc3c2 | ||
![]() |
8bd5b1b988 | ||
![]() |
2b8f7fd6d8 | ||
![]() |
b99addef4a | ||
![]() |
96ada80ce1 | ||
![]() |
5d33c79369 | ||
![]() |
645ab89437 | ||
![]() |
62b342cdbb | ||
![]() |
c235a4ff16 | ||
![]() |
a24516a4d5 | ||
![]() |
483b1fc27d | ||
![]() |
4d0de82986 | ||
![]() |
85663341eb | ||
![]() |
734043dee6 | ||
![]() |
af2927f05b | ||
![]() |
3e54b1d7bb | ||
![]() |
51a0ce220c | ||
![]() |
05e20e3bab | ||
![]() |
03fc2c42ad | ||
![]() |
401172eb36 | ||
![]() |
71f1132bc8 | ||
![]() |
605486feda | ||
![]() |
23597e800d | ||
![]() |
3218d87b1b | ||
![]() |
0c58a6c92c | ||
![]() |
afa3006de2 | ||
![]() |
03b9bf9e7a | ||
![]() |
028c0d3e06 | ||
![]() |
0005488884 | ||
![]() |
f73f25708c | ||
![]() |
4e411aaa6b | ||
![]() |
6adeab7586 | ||
![]() |
16f6b7f979 | ||
![]() |
068f363f09 | ||
![]() |
d4554c6429 | ||
![]() |
a3caa6485c | ||
![]() |
795d55a2cd | ||
![]() |
c53c1a27a4 | ||
![]() |
903cc6bd8e | ||
![]() |
13929acbd1 | ||
![]() |
f6da130fce | ||
![]() |
1fc793c3fd | ||
![]() |
4b6ac1a415 | ||
![]() |
304010db40 | ||
![]() |
66563c9d95 | ||
![]() |
5eca4c045b | ||
![]() |
fd953e7a71 | ||
![]() |
52b20cb491 | ||
![]() |
c987d2800d | ||
![]() |
6d6bacd6a1 | ||
![]() |
f0a0c9228f | ||
![]() |
dfef9e5233 | ||
![]() |
ab77af9e5d | ||
![]() |
5ce06c6214 | ||
![]() |
d5cc80d1f2 | ||
![]() |
e3f04192b8 | ||
![]() |
cfb8435373 | ||
![]() |
615f2abed1 | ||
![]() |
ac926e84d7 | ||
![]() |
8846b96905 | ||
![]() |
677e99ffd9 | ||
![]() |
a82b30179b | ||
![]() |
ae4e9be739 | ||
![]() |
7091a4016a | ||
![]() |
24b292bf33 | ||
![]() |
c00f006cdd | ||
![]() |
ed47a41c9c | ||
![]() |
39cc92853a | ||
![]() |
34f7563bed | ||
![]() |
964d7b38a8 | ||
![]() |
17fbbca046 | ||
![]() |
64faf296a6 | ||
![]() |
f1c404a443 | ||
![]() |
5ed1312406 | ||
![]() |
00c18451cc | ||
![]() |
b737b5c748 | ||
![]() |
d852990314 | ||
![]() |
182073f41e | ||
![]() |
64d3a11866 | ||
![]() |
4865e85655 | ||
![]() |
3d6095d652 | ||
![]() |
bd0e379d01 | ||
![]() |
93395a8aa5 | ||
![]() |
339437f47f | ||
![]() |
80db7edf18 | ||
![]() |
41e86a9e51 | ||
![]() |
ef04678947 | ||
![]() |
1a964a283f | ||
![]() |
6c47375d18 | ||
![]() |
c2abce1e35 | ||
![]() |
b4b715f6e4 | ||
![]() |
8a7c954d88 | ||
![]() |
639f7605d1 | ||
![]() |
fbcf9809c5 | ||
![]() |
2474765820 | ||
![]() |
ba4507bd22 | ||
![]() |
2610c44ac9 | ||
![]() |
f608282aa5 | ||
![]() |
781f376bea | ||
![]() |
6e1c3b95c2 | ||
![]() |
0331eb7b25 | ||
![]() |
c3a210907a | ||
![]() |
3e0f1f16c1 | ||
![]() |
c2be25271b | ||
![]() |
bb131a7f53 | ||
![]() |
c753865305 | ||
![]() |
0bac7deccc | ||
![]() |
9ada9f9e68 | ||
![]() |
02b9e20ce3 | ||
![]() |
3c8cf996b5 | ||
![]() |
313e2eb06f | ||
![]() |
41fcbba5cc | ||
![]() |
ce9916a792 | ||
![]() |
3f830458b1 | ||
![]() |
a8e24b7629 | ||
![]() |
80f5cb5f46 | ||
![]() |
d45aa752c6 | ||
![]() |
58501a74a7 | ||
![]() |
80c1a04797 | ||
![]() |
af3abe66f4 |
93 changed files with 9059 additions and 833 deletions
18
.github/ISSUE_TEMPLATE/issue_form.yml
vendored
18
.github/ISSUE_TEMPLATE/issue_form.yml
vendored
|
@ -34,15 +34,15 @@ body:
|
|||
required: true
|
||||
- label: I observed this bug on a clean install of a [supported OS](https://docs.raspap.com/#compatible-operating-systems).
|
||||
required: true
|
||||
- label: I have followed the [project prerequisites](https://docs.raspap.com/#quick-start).
|
||||
- label: I have followed the [project prerequisites](https://docs.raspap.com/quick_start/#quick-install).
|
||||
required: true
|
||||
- label: I have searched this repository for existing issues.
|
||||
required: true
|
||||
- label: I checked the [FAQ](https://docs.raspap.com/faq/) and [official documentation](https://docs.raspap.com/).
|
||||
required: true
|
||||
- label: I am using an [external wireless adapter](https://docs.raspap.com/issues/#external-hardware).
|
||||
required: true
|
||||
- label: I have generated a [RaspAP debug log](https://docs.raspap.com/ap-basics/#debug-log) and performed a [self-diagnosis](https://docs.raspap.com/ap-basics/#diagnosing-problems).
|
||||
required: false
|
||||
- label: I have generated a [RaspAP debug log](https://docs.raspap.com/troubleshooting/#debug-log) and performed a [self-diagnosis](https://docs.raspap.com/troubleshooting/#diagnosing-problems).
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
|
@ -56,15 +56,15 @@ body:
|
|||
- Raspberry Pi OS (64-bit) Lite Bullseye
|
||||
- Raspberry Pi OS (32-bit) Lite Bullseye
|
||||
- Armbian 23.05 (Suni)
|
||||
- Debian Bookworm
|
||||
- Ubuntu Server 23.04 (Lunar)
|
||||
- Debian Bookworm
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: install
|
||||
attributes:
|
||||
label: Quick install or Manual setup?
|
||||
label: Installation method
|
||||
options:
|
||||
- Pre-built image
|
||||
- Quick install
|
||||
- Manual setup
|
||||
validations:
|
||||
|
@ -90,6 +90,7 @@ body:
|
|||
- Raspberry Pi 3 Model B
|
||||
- Raspberry Pi Zero 2 W
|
||||
- Raspberry Pi Zero W
|
||||
- Raspberry Pi Compute Module
|
||||
- Orange Pi family
|
||||
- Other
|
||||
validations:
|
||||
|
@ -99,8 +100,8 @@ body:
|
|||
attributes:
|
||||
label: RaspAP version
|
||||
options:
|
||||
- 3.2.5 (Latest)
|
||||
- Other
|
||||
- Latest
|
||||
- Other (specify below)
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
@ -113,7 +114,6 @@ body:
|
|||
- Not sure
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: contact
|
||||
attributes:
|
||||
|
|
5
.gitmodules
vendored
5
.gitmodules
vendored
|
@ -1,3 +1,4 @@
|
|||
[submodule "plugins"]
|
||||
path = plugins
|
||||
url = https://github.com/RaspAP/plugins
|
||||
path = plugins
|
||||
url = https://github.com/RaspAP/plugins
|
||||
branch = master
|
||||
|
|
|
@ -20,7 +20,6 @@ The following features are currently available exclusively to sponsors. A tangib
|
|||
✅ [WPA3-Personal AP security](https://docs.raspap.com/ap-basics/#wpa3-personal)
|
||||
✅ [802.11w Protected Management Frames](https://docs.raspap.com/ap-basics/#80211w)
|
||||
✅ [Printable Wi-Fi signs](https://docs.raspap.com/ap-basics/#printable-signs)
|
||||
✅ [Drag & drop dashboard widgets](https://docs.raspap.com/ap-basics/#drag-drop-widgets)
|
||||
✅ [MAC address cloning](https://docs.raspap.com/net-devices/#changing-the-mac-address)
|
||||
✅ [Network diagnostics](https://docs.raspap.com/net-devices/#diagnostics)
|
||||
✅ [WireGuard VPN kill switch](https://docs.raspap.com/wireguard/#kill-switch)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||

|
||||
[](https://github.com/raspap/raspap-webgui/releases) [](https://github.com/thibmaek/awesome-raspberry-pi) [](https://github.com/sponsors/RaspAP) [](https://app.travis-ci.com/RaspAP/raspap-webgui) [](https://crowdin.com/project/raspap) [](https://twitter.com/rasp_ap) [](https://reddit.com/r/RaspAP) [](https://discord.gg/KVAsaAR)
|
||||
[](https://github.com/raspap/raspap-webgui/releases) [](https://github.com/thibmaek/awesome-raspberry-pi) [](https://github.com/sponsors/RaspAP) [](https://app.travis-ci.com/RaspAP/raspap-webgui) [](https://crowdin.com/project/raspap) [](https://twitter.com/rasp_ap) [](https://reddit.com/r/RaspAP) [](https://discord.gg/KVAsaAR)
|
||||
|
||||
RaspAP is feature-rich wireless router software that _just works_ on many popular [Debian-based devices](#supported-operating-systems), including the Raspberry Pi. Our [custom OS images](#pre-built-image), [Quick installer](#quick-installer) and [Docker container](#docker-support) create a known-good default configuration for all current Raspberry Pis with onboard wireless. A fully responsive, mobile-ready interface gives you control over the relevant services and networking options. Advanced DHCP settings, WireGuard and OpenVPN support, [SSL certificates](https://docs.raspap.com/ssl/), [ad blocking](#ad-blocking), security audits, [captive portal integration](https://docs.raspap.com/captive/), themes and [multilingual options](https://docs.raspap.com/translations/) are included.
|
||||
|
||||
|
@ -7,7 +7,7 @@ RaspAP has been featured by [PC World](https://www.pcwelt.de/article/1789512/ras
|
|||
|
||||
We hope you enjoy using RaspAP as much as we do creating it. Tell us how you use this with [your own projects](https://github.com/raspap/raspap-awesome).
|
||||
|
||||

|
||||

|
||||
<img width="32.5%" alt="Wifi Client" src="https://github.com/user-attachments/assets/95696ddc-da84-4339-97cc-f2a173054664">
|
||||
<img width="32.5%" alt="Hotspot" src="https://github.com/user-attachments/assets/c1c4de15-3ff2-4d3c-a7af-339c24896749">
|
||||
<img width="32.5%" alt="Adblock" src="https://github.com/user-attachments/assets/ab925687-8407-4bec-a952-9dc6a2675f49">
|
||||
|
@ -146,9 +146,8 @@ RaspAP was originally made for Raspbian, but now also installs on the following
|
|||
| Raspberry Pi OS | (32-bit) Lite Bullseye | ARM | Official |
|
||||
| Armbian | 23.11 (Jammy) | [ARM](https://docs.armbian.com/#supported-socs) | Beta |
|
||||
| Debian | Bookworm | ARM / x86_64 | Beta |
|
||||
| Ubuntu | Server 23.04 (Lunar) | ARM / x86_64 | Beta |
|
||||
|
||||
<img src="https://github.com/RaspAP/raspap-webgui/assets/229399/6fe62f2d-631a-46c9-8ceb-83ebf0ade6a9" style="width:640px;" />
|
||||
<img src="https://i.imgur.com/XiAJNKb.png" style="width:480px;" />
|
||||
|
||||
You are also encouraged to use RaspAP's community-led [Docker container](#docker-support). Please note that "supported" is not a guarantee. If you are able to improve support for your preferred distro, we encourage you to [actively contribute](#how-to-contribute) to the project.
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
if (isset($_POST['blocklist_id'])) {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
$interface = filter_input(INPUT_GET, 'inet', FILTER_SANITIZE_SPECIAL_CHARS);
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
if (filter_input(INPUT_GET, 'tu') == 'h') {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../includes/functions.php';
|
||||
|
||||
|
|
|
@ -1,37 +1,29 @@
|
|||
<?php
|
||||
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/functions.php';
|
||||
|
||||
if (isset($_POST['csrf_token'])) {
|
||||
if (csrfValidateRequest() && !CSRFValidate()) {
|
||||
handleInvalidCSRFToken();
|
||||
}
|
||||
$return = 0;
|
||||
$path = "../../config";
|
||||
$configs = array(
|
||||
array("src" => $path .'/hostapd.conf', "tmp" => "/tmp/hostapddata", "dest" => RASPI_HOSTAPD_CONFIG),
|
||||
array("src" => $path .'/dhcpcd.conf', "tmp" => "/tmp/dhcpddata", "dest" => RASPI_DHCPCD_CONFIG),
|
||||
array("src" => $path .'/090_wlan0.conf', "tmp" => "/tmp/dnsmasqdata", "dest" => RASPI_DNSMASQ_PREFIX.'wlan0.conf'),
|
||||
array("src" => $path .'/090_raspap.conf', "tmp" => "/tmp/dnsmasqdata", "dest" => RASPI_DNSMASQ_PREFIX.'raspap.conf'),
|
||||
);
|
||||
$return = 0;
|
||||
$path = "../../config";
|
||||
$configs = array(
|
||||
array("src" => $path .'/hostapd.conf', "tmp" => "/tmp/hostapddata", "dest" => RASPI_HOSTAPD_CONFIG),
|
||||
array("src" => $path .'/dhcpcd.conf', "tmp" => "/tmp/dhcpddata", "dest" => RASPI_DHCPCD_CONFIG),
|
||||
array("src" => $path .'/090_wlan0.conf', "tmp" => "/tmp/dnsmasqdata", "dest" => RASPI_DNSMASQ_PREFIX.'wlan0.conf'),
|
||||
array("src" => $path .'/090_raspap.conf', "tmp" => "/tmp/dnsmasqdata", "dest" => RASPI_DNSMASQ_PREFIX.'raspap.conf'),
|
||||
);
|
||||
|
||||
foreach ($configs as $config) {
|
||||
try {
|
||||
$tmp = file_get_contents($config["src"]);
|
||||
file_put_contents($config["tmp"], $tmp);
|
||||
system("sudo cp ".$config["tmp"]. " ".$config["dest"]);
|
||||
} catch (Exception $e) {
|
||||
$return = $e->getCode();
|
||||
}
|
||||
foreach ($configs as $config) {
|
||||
try {
|
||||
$tmp = file_get_contents($config["src"]);
|
||||
file_put_contents($config["tmp"], $tmp);
|
||||
system("sudo cp ".$config["tmp"]. " ".$config["dest"]);
|
||||
} catch (Exception $e) {
|
||||
$return = $e->getCode();
|
||||
}
|
||||
$jsonData = ['return'=>$return];
|
||||
echo json_encode($jsonData);
|
||||
|
||||
} else {
|
||||
handleInvalidCSRFToken();
|
||||
}
|
||||
$jsonData = ['return'=>$return];
|
||||
echo json_encode($jsonData);
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
exec("ls /sys/class/net | grep -v lo", $interfaces);
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
exec('cat '. RASPI_HOSTAPD_CONFIG, $hostapdconfig);
|
||||
|
@ -18,3 +17,4 @@ foreach ($hostapdconfig as $hostapdconfigline) {
|
|||
};
|
||||
$channel = intval($arrConfig['channel']);
|
||||
echo json_encode($channel);
|
||||
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../src/RaspAP/Parsers/IwParser.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
if (isset($_POST['interface'])) {
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/functions.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
if (isset($_POST['interface'])) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../includes/functions.php';
|
||||
|
||||
$interface = $_POST['iface'];
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../includes/locale.php';
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
// fetch wg client.conf
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
$entity = escapeshellcmd($_POST['entity']);
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../includes/defaults.php';
|
||||
require_once '../../includes/functions.php';
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../includes/functions.php';
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../includes/functions.php';
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../src/RaspAP/Plugins/PluginInstaller.php';
|
||||
|
||||
$pluginInstaller = \RaspAP\Plugins\PluginInstaller::getInstance();
|
||||
$plugin_uri = $_POST['plugin_uri'] ?? null;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
$lastActivity = $_SESSION['lastActivity'] ?? time();
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
$action = escapeshellcmd($_POST['a']);
|
||||
|
|
|
@ -1,27 +1,22 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
require_once '../../includes/defaults.php';
|
||||
require_once '../../includes/functions.php';
|
||||
|
||||
if (isset($_POST['csrf_token'])) {
|
||||
if (csrfValidateRequest() && !CSRFValidate()) {
|
||||
handleInvalidCSRFToken();
|
||||
}
|
||||
$uri = RASPI_API_ENDPOINT;
|
||||
preg_match('/(\d+(\.\d+)+)/', RASPI_VERSION, $matches);
|
||||
$thisRelease = $matches[0];
|
||||
$uri = RASPI_API_ENDPOINT;
|
||||
preg_match('/(\d+(\.\d+)+)/', RASPI_VERSION, $matches);
|
||||
$thisRelease = $matches[0];
|
||||
|
||||
$json = shell_exec("wget --timeout=5 --tries=1 $uri -qO -");
|
||||
$data = json_decode($json, true);
|
||||
$tagName = $data['tag_name'];
|
||||
$updateAvailable = checkReleaseVersion($thisRelease, $tagName);
|
||||
$json = shell_exec("wget --timeout=5 --tries=1 $uri -qO -");
|
||||
$data = json_decode($json, true);
|
||||
$tagName = $data['tag_name'];
|
||||
$updateAvailable = checkReleaseVersion($thisRelease, $tagName);
|
||||
|
||||
$response['tag'] = $tagName;
|
||||
$response['update'] = $updateAvailable;
|
||||
echo json_encode($response);
|
||||
$response['tag'] = $tagName;
|
||||
$response['update'] = $updateAvailable;
|
||||
echo json_encode($response);
|
||||
|
||||
} else {
|
||||
handleInvalidCSRFToken();
|
||||
}
|
||||
|
|
|
@ -1,25 +1,18 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
if (isset($_POST['csrf_token'])) {
|
||||
if (csrfValidateRequest() && !CSRFValidate()) {
|
||||
handleInvalidCSRFToken();
|
||||
}
|
||||
$root = getenv("DOCUMENT_ROOT");
|
||||
exec('sudo '.RASPI_CONFIG.'/system/debuglog.sh -i '.$root, $return);
|
||||
$root = getenv("DOCUMENT_ROOT");
|
||||
exec('sudo '.RASPI_CONFIG.'/system/debuglog.sh -i '.$root, $return);
|
||||
|
||||
$logOutput = implode(PHP_EOL, $return);
|
||||
$tempDir = sys_get_temp_dir();
|
||||
$filePath = $tempDir . DIRECTORY_SEPARATOR . RASPI_DEBUG_LOG;
|
||||
$handle = fopen($filePath, "w");
|
||||
fwrite($handle, $logOutput);
|
||||
fclose($handle);
|
||||
echo json_encode($filePath);
|
||||
|
||||
$logOutput = implode(PHP_EOL, $return);
|
||||
$tempDir = sys_get_temp_dir();
|
||||
$filePath = $tempDir . DIRECTORY_SEPARATOR . RASPI_DEBUG_LOG;
|
||||
$handle = fopen($filePath, "w");
|
||||
fwrite($handle, $logOutput);
|
||||
fclose($handle);
|
||||
echo json_encode($filePath);
|
||||
} else {
|
||||
handleInvalidCSRFToken();
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
$tempDir = sys_get_temp_dir();
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<?php
|
||||
|
||||
require '../../includes/csrf.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/CSRF.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
if (isset($_POST['csrf_token'])) {
|
||||
|
@ -12,7 +11,7 @@ if (isset($_POST['csrf_token'])) {
|
|||
}
|
||||
// set installer path + options
|
||||
$path = getenv("DOCUMENT_ROOT");
|
||||
$opts = " --update --yes --path $path";
|
||||
$opts = " --update --yes --check 0 --path $path";
|
||||
$installer = "sudo /etc/raspap/system/raspbian.sh";
|
||||
$execUpdate = $installer.$opts;
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../includes/autoload.php';
|
||||
require_once '../../includes/session.php';
|
||||
require_once '../../src/RaspAP/Auth/HTTPAuth.php';
|
||||
require_once '../../includes/config.php';
|
||||
require_once '../../includes/authenticate.php';
|
||||
|
||||
$logFile = '/tmp/raspap_install.log';
|
||||
|
|
287
app/css/all.css
287
app/css/all.css
|
@ -9,6 +9,7 @@ License: GNU General Public License v3.0
|
|||
:root {
|
||||
--raspap-content-main: #495057;
|
||||
--raspap-text-muted: #858796;
|
||||
--raspap-text-light: #999999;
|
||||
--raspap-brand-color: #2b8080;
|
||||
--raspap-offwhite: #faf9f6;
|
||||
}
|
||||
|
@ -168,12 +169,7 @@ th {
|
|||
}
|
||||
|
||||
canvas#divDBChartBandwidthhourly {
|
||||
height: 350px!important;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: 150px;
|
||||
width: 200px;
|
||||
height: 509px!important;
|
||||
}
|
||||
|
||||
.dbChart {
|
||||
|
@ -190,7 +186,7 @@ canvas#divDBChartBandwidthhourly {
|
|||
}
|
||||
|
||||
.check-progress {
|
||||
color: #999;
|
||||
color: var(--raspap-text-light);
|
||||
}
|
||||
|
||||
.fa-check {
|
||||
|
@ -388,3 +384,280 @@ textarea.plugin-log {
|
|||
font-family: monospace;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.card-wrapper {
|
||||
margin: 1rem;
|
||||
}
|
||||
|
||||
.dashboard-container {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
min-height: 400px;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.connections-left,
|
||||
.connections-right {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.connection-item {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
z-index: 5;
|
||||
color: var(--raspap-text-light);
|
||||
}
|
||||
|
||||
.connection-right {
|
||||
align-items: center;
|
||||
margin-left: 10rem;
|
||||
}
|
||||
|
||||
.connections-left i {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: left;
|
||||
}
|
||||
|
||||
.connections-left i:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.connections-left i:last-child {
|
||||
margin-bottom: 0;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.center-device {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.center-device-top {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.client-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row-reverse;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.client-count {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.clients-status {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
.dashed-lines,
|
||||
.solid-lines {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
padding: 1rem;
|
||||
left: 112px;
|
||||
}
|
||||
|
||||
.dashed-lines-right,
|
||||
.solid-lines-right {
|
||||
left: -80px;
|
||||
}
|
||||
|
||||
.solid-lines, .solid-lines-right {
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.dashed-lines, .dashed-lines-right {
|
||||
z-index 0;
|
||||
}
|
||||
|
||||
.device-status {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin: 0.8rem 0;
|
||||
}
|
||||
|
||||
.wifi-bands {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.band {
|
||||
padding: 0.25rem 1rem;
|
||||
border: 2px solid var(--raspap-text-light);
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
font-weight: 600;
|
||||
color: var(--raspap-text-light);
|
||||
}
|
||||
|
||||
.band.active {
|
||||
border-color: var(--raspap-theme-color);
|
||||
color: var(--raspap-theme-color);
|
||||
}
|
||||
|
||||
.device-label {
|
||||
font-size: 1.3rem;
|
||||
text-align: center;
|
||||
color: var(--raspap-theme-color);
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.status-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1.3rem;
|
||||
color: var(--raspap-text-light);
|
||||
}
|
||||
|
||||
.bottom {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 1.3rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.status-item .fa-stack {
|
||||
width: 1.5em!important;
|
||||
}
|
||||
|
||||
.connection-item>i {
|
||||
color: var(--raspap-text-light);
|
||||
}
|
||||
|
||||
.connection-item .fa-stack {
|
||||
min-width: 2.5em;
|
||||
}
|
||||
|
||||
.connections-left>.connection-item>span {
|
||||
color: var(--raspap-text-light);
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.inactive {
|
||||
color: var(--raspap-text-light)!important;
|
||||
}
|
||||
|
||||
a.inactive:hover,
|
||||
a.inactive:focus {
|
||||
color: var(--raspap-text-light) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
.connection-item a > span:not(.fa-stack) {
|
||||
display: none!important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.connections-right,
|
||||
.connections-left {
|
||||
display: none!important;
|
||||
}
|
||||
.dashboard-container {
|
||||
width: auto;
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
.device-status {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.clients-mobile {
|
||||
display: flex!important;
|
||||
flex-direction: row!important;
|
||||
}
|
||||
}
|
||||
.connection-item.active > span {
|
||||
color: var(--raspap-theme-color)!important;
|
||||
}
|
||||
.connection-item.active > i {
|
||||
color: var(--raspap-theme-color)!important;
|
||||
}
|
||||
.status-item.active > span {
|
||||
color: var(--raspap-theme-color)!important;
|
||||
}
|
||||
.status-item.active > i {
|
||||
color: var(--raspap-theme-color)!important;
|
||||
}
|
||||
|
||||
.clients-mobile {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.client-type {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.client-type i {
|
||||
font-size: 1.5rem;
|
||||
color: var(--raspap-theme-color);
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 2px solid var(--raspap-theme-color);
|
||||
}
|
||||
|
||||
.client-type i.badge-icon {
|
||||
font-size: 0.7rem;
|
||||
background: var(--raspap-theme-color);
|
||||
color: var(--raspap-offwhite);
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.client-count {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
background: var(--raspap-theme-color);
|
||||
color: var(--raspap-offwhite);
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.device-illustration {
|
||||
min-width: 220px;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
|
|
54
app/img/dashed.svg
Normal file
54
app/img/dashed.svg
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 227 596" style="enable-background:new 0 0 227 596;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#999999;stroke-width:3;}
|
||||
.st1{fill:none;stroke:#999999;stroke-width:3;stroke-dasharray:6.0204,3.0102;}
|
||||
.st2{fill:none;stroke:#999999;stroke-width:3;stroke-dasharray:5.7963,2.8981;}
|
||||
</style>
|
||||
<g id="dashed">
|
||||
<g id="Line_1">
|
||||
<g>
|
||||
<line class="st0" x1="112.8" y1="0" x2="112.8" y2="3"/>
|
||||
<line class="st1" x1="112.8" y1="6" x2="112.8" y2="591.5"/>
|
||||
<line class="st0" x1="112.8" y1="593" x2="112.8" y2="596"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Line_2">
|
||||
<g>
|
||||
<line class="st0" x1="113.2" y1="0.8" x2="110.2" y2="0.8"/>
|
||||
<line class="st2" x1="107.3" y1="0.8" x2="4.4" y2="0.8"/>
|
||||
<line class="st0" x1="3" y1="0.8" x2="0" y2="0.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Line_3">
|
||||
<g>
|
||||
<line class="st0" x1="113.2" y1="198.9" x2="110.2" y2="198.9"/>
|
||||
<line class="st2" x1="107.3" y1="198.9" x2="4.4" y2="198.9"/>
|
||||
<line class="st0" x1="3" y1="198.9" x2="0" y2="198.9"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Line_4">
|
||||
<g>
|
||||
<line class="st0" x1="113.2" y1="397.1" x2="110.2" y2="397.1"/>
|
||||
<line class="st2" x1="107.3" y1="397.1" x2="4.4" y2="397.1"/>
|
||||
<line class="st0" x1="3" y1="397.1" x2="0" y2="397.1"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Line_5">
|
||||
<g>
|
||||
<line class="st0" x1="113.2" y1="595.2" x2="110.2" y2="595.2"/>
|
||||
<line class="st2" x1="107.3" y1="595.2" x2="4.4" y2="595.2"/>
|
||||
<line class="st0" x1="3" y1="595.2" x2="0" y2="595.2"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Line_6">
|
||||
<g>
|
||||
<line class="st0" x1="226.2" y1="297.8" x2="223.2" y2="297.8"/>
|
||||
<line class="st2" x1="220.3" y1="297.8" x2="117.4" y2="297.8"/>
|
||||
<line class="st0" x1="116" y1="297.8" x2="113" y2="297.8"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
1083
app/img/devices/compute.php
Normal file
1083
app/img/devices/compute.php
Normal file
File diff suppressed because it is too large
Load diff
4450
app/img/devices/default.php
Normal file
4450
app/img/devices/default.php
Normal file
File diff suppressed because it is too large
Load diff
1561
app/img/devices/zero.php
Normal file
1561
app/img/devices/zero.php
Normal file
File diff suppressed because it is too large
Load diff
40
app/img/right-dashed.svg
Normal file
40
app/img/right-dashed.svg
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 314 594" style="enable-background:new 0 0 314 594;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#999999;stroke-width:3;}
|
||||
.st1{fill:none;stroke:#999999;stroke-width:3;stroke-dasharray:6.04,3.02;}
|
||||
.st2{fill:none;stroke:#999999;stroke-width:3;stroke-dasharray:5.7963,2.8981;}
|
||||
</style>
|
||||
<g id="dashed">
|
||||
<g id="horizontal">
|
||||
<g>
|
||||
<line class="st0" x1="113.2" y1="144" x2="113.2" y2="147"/>
|
||||
<line class="st1" x1="113.2" y1="150" x2="113.3" y2="447.5"/>
|
||||
<line class="st0" x1="113.3" y1="449" x2="113.3" y2="452"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="top">
|
||||
<g>
|
||||
<line class="st0" x1="114" y1="144.8" x2="117" y2="144.8"/>
|
||||
<line class="st2" x1="119.9" y1="144.8" x2="222.8" y2="144.8"/>
|
||||
<line class="st0" x1="224.2" y1="144.8" x2="227.2" y2="144.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="out">
|
||||
<g>
|
||||
<line class="st0" x1="0" y1="297.8" x2="3" y2="297.8"/>
|
||||
<line class="st2" x1="5.9" y1="297.8" x2="108.8" y2="297.8"/>
|
||||
<line class="st0" x1="110.2" y1="297.8" x2="113.2" y2="297.8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="bottom">
|
||||
<g>
|
||||
<line class="st0" x1="113" y1="450.8" x2="116" y2="450.8"/>
|
||||
<line class="st2" x1="118.9" y1="450.8" x2="221.8" y2="450.8"/>
|
||||
<line class="st0" x1="223.2" y1="450.8" x2="226.2" y2="450.8"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
46
app/img/right-solid.php
Normal file
46
app/img/right-solid.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
header("Content-Type: image/svg+xml");
|
||||
$showDevice1 = isset($_GET['device-1']);
|
||||
$showOut = isset($_GET['out']);
|
||||
$showDevice2 = isset($_GET['device-2']);
|
||||
?>
|
||||
|
||||
<svg width="313" height="594" viewBox="0 0 313 594" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Frame 1">
|
||||
<g id="right connection frame">
|
||||
<g id="solid">
|
||||
<?php if ($showDevice2): ?>
|
||||
<line id="joint-device-2" y1="-0.75" x2="154" y2="-0.75"
|
||||
transform="matrix(4.37114e-08 1 1 -4.37114e-08 114 297)"
|
||||
stroke="#008281" stroke-width="4"/>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($showDevice1): ?>
|
||||
<line id="joint-device-1" style="display: inline;"
|
||||
y1="-0.75" x2="154" y2="-0.75"
|
||||
transform="matrix(4.37114e-08 1 1 -4.37114e-08 114 144)"
|
||||
stroke="#008281" stroke-width="4"/>
|
||||
|
||||
<line id="device-1" style="display: inline;"
|
||||
y1="-0.75" x2="113.231" y2="-0.75"
|
||||
transform="matrix(1 8.74228e-08 8.74228e-08 -1 114 144)"
|
||||
stroke="#008281" stroke-width="4"/>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($showOut): ?>
|
||||
<line id="out" style="display: inline;"
|
||||
y1="-0.75" x2="113.231" y2="-0.75"
|
||||
transform="matrix(1 8.74228e-08 8.74228e-08 -1 -0.000305176 297)"
|
||||
stroke="#008281" stroke-width="4"/>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($showDevice2): ?>
|
||||
<line id="device-2" style="display: inline;"
|
||||
y1="-0.75" x2="113.231" y2="-0.75"
|
||||
transform="matrix(1 8.74228e-08 8.74228e-08 -1 113 450)"
|
||||
stroke="#008281" stroke-width="4"/>
|
||||
<?php endif; ?>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
65
app/img/solid.php
Normal file
65
app/img/solid.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
header("Content-Type: image/svg+xml");
|
||||
|
||||
require_once '../../includes/functions.php';
|
||||
$color = getColorOpt();
|
||||
|
||||
$showJoint = isset($_GET['joint']);
|
||||
$showDevice1 = isset($_GET['device-1']);
|
||||
$showOut = isset($_GET['out']);
|
||||
$showDevice2 = isset($_GET['device-2']);
|
||||
$showDevice3 = isset($_GET['device-3']);
|
||||
$showDevice4 = isset($_GET['device-4']);
|
||||
?>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="227" height="596" viewBox="0 0 227 596" fill="none">
|
||||
<?php
|
||||
// Device positions array (y-coordinates)
|
||||
$devicePositions = [
|
||||
'device-1' => 0.75,
|
||||
'out' => 297.75,
|
||||
'device-2' => 198.75,
|
||||
'device-3' => 397.058,
|
||||
'device-4' => 595.211
|
||||
];
|
||||
|
||||
// Calculate joint line segments
|
||||
if ($showJoint) {
|
||||
$activeDevices = array_filter([$showDevice1, $showDevice2, $showDevice3, $showDevice4]);
|
||||
$activeYs = [];
|
||||
|
||||
foreach ($devicePositions as $device => $y) {
|
||||
if (isset($_GET[$device])) {
|
||||
$activeYs[] = $y;
|
||||
}
|
||||
}
|
||||
|
||||
// Add top/bottom if first/last device is connected
|
||||
if ($showDevice1) array_unshift($activeYs, 0);
|
||||
if ($showDevice4) $activeYs[] = 596;
|
||||
|
||||
// Draw segments between consecutive points
|
||||
for ($i = 1; $i < count($activeYs); $i++) {
|
||||
$y1 = $activeYs[$i-1];
|
||||
$y2 = $activeYs[$i];
|
||||
echo "<line x1='112.75' y1='$y1' x2='112.75' y2='$y2' stroke='$color' stroke-width='4'/>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if ($showDevice1): ?>
|
||||
<line x1="113.231" y1="0.75" x2="7.69496e-06" y2="0.75001" stroke="<?php echo $color; ?>" stroke-width="6" id="device-1"/>
|
||||
<?php endif; ?>
|
||||
<?php if ($showOut): ?>
|
||||
<line x1="226.231" y1="297.75" x2="113" y2="297.75" stroke="<?php echo $color; ?>" stroke-width="4" id="out"/>
|
||||
<?php endif; ?>
|
||||
<?php if ($showDevice2): ?>
|
||||
<line x1="113.231" y1="198.75" x2="7.69496e-06" y2="198.75" stroke="<?php echo $color; ?>" stroke-width="4" id="device-2"/>
|
||||
<?php endif; ?>
|
||||
<?php if ($showDevice3): ?>
|
||||
<line x1="113.231" y1="397.058" x2="7.69496e-06" y2="397.058" stroke="<?php echo $color; ?>" stroke-width="4" id="device-3"/>
|
||||
<?php endif; ?>
|
||||
<?php if ($showDevice4): ?>
|
||||
<line x1="113.231" y1="595.211" x2="7.69496e-06" y2="595.211" stroke="<?php echo $color; ?>" stroke-width="4" id="device-4"/>
|
||||
<?php endif; ?>
|
||||
</svg>
|
29
app/img/uri-qr-code.php
Executable file
29
app/img/uri-qr-code.php
Executable file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
if (!isset($_GET['uri']) || !filter_var($_GET['uri'], FILTER_VALIDATE_URL)) {
|
||||
header("HTTP/1.1 400 Bad Request");
|
||||
exit("Invalid or missing URI parameter");
|
||||
}
|
||||
|
||||
$uri = $_GET['uri'];
|
||||
$command = "qrencode -t svg -m 0 -o - " . escapeshellarg($uri);
|
||||
|
||||
$svg = shell_exec($command);
|
||||
if ($svg === null) {
|
||||
error_log("QR generation failed for URI: $uri");
|
||||
header("HTTP/1.1 500 Internal Server Error");
|
||||
exit("Failed to generate QR code");
|
||||
}
|
||||
|
||||
$etag = hash('sha256', $uri);
|
||||
$content_length = strlen($svg);
|
||||
$last_modified = gmdate("D, d M Y H:i:s") . " GMT";
|
||||
|
||||
header("Content-Type: image/svg+xml");
|
||||
header("Content-Length: $content_length");
|
||||
header("Last-Modified: $last_modified");
|
||||
header("ETag: \"$etag\"");
|
||||
header("X-QR-Code-Content: " . htmlspecialchars($uri, ENT_QUOTES, 'UTF-8'));
|
||||
|
||||
echo $svg;
|
||||
|
|
@ -13,6 +13,7 @@ if (!isset($_SERVER['HTTP_REFERER'])) {
|
|||
exec("sudo cat " .RASPI_WIREGUARD_PATH.'client.conf', $return);
|
||||
$peer_conf = implode(PHP_EOL,$return);
|
||||
$peer_conf.= PHP_EOL;
|
||||
$peer_conf_sanitized = str_replace(["\r", "\n"], '', $peer_conf);
|
||||
$command = "qrencode -t svg -m 0 -o - " . mb_escapeshellarg($peer_conf);
|
||||
$svg = shell_exec($command);
|
||||
$etag = hash('sha256', $peer_conf);
|
||||
|
@ -23,6 +24,6 @@ header("Content-Type: image/svg+xml");
|
|||
header("Content-Length: $content_length");
|
||||
header("Last-Modified: $last_modified");
|
||||
header("ETag: \"$etag\"");
|
||||
header("X-QR-Code-Content: $peer_conf");
|
||||
header("X-QR-Code-Content: $peer_conf_sanitized");
|
||||
echo shell_exec($command);
|
||||
|
||||
|
|
|
@ -12,12 +12,12 @@ if (!isset($_SERVER['HTTP_REFERER'])) {
|
|||
|
||||
$hostapd = parse_ini_file(RASPI_HOSTAPD_CONFIG, false, INI_SCANNER_RAW);
|
||||
|
||||
// assume wpa encryption and get the passphrase
|
||||
// assume WPA encryption and get the passphrase
|
||||
$type = "WPA";
|
||||
$password = isset($hostapd['wpa_psk']) ? $hostapd['wpa_psk'] : $hostapd['wpa_passphrase'];
|
||||
|
||||
// use wep if configured
|
||||
$wep_default_key = intval($hostapd['wep_default_key']);
|
||||
// use WEP if configured
|
||||
$wep_default_key = intval($hostapd['wep_default_key'] ?? 0);
|
||||
$wep_key = 'wep_key' . $wep_default_key;
|
||||
if (array_key_exists($wep_key, $hostapd)) {
|
||||
$type = "WEP";
|
||||
|
@ -30,7 +30,7 @@ if (empty($password)) {
|
|||
}
|
||||
|
||||
$ssid = $hostapd['ssid'];
|
||||
$hidden = intval($hostapd['ignore_broadcast_ssid']) != 0 ? "H:true" : "";
|
||||
$hidden = intval($hostapd['ignore_broadcast_ssid'] ?? 0) !== 0 ? "H:true" : "";
|
||||
|
||||
$ssid = qr_encode($ssid);
|
||||
$password = qr_encode($password);
|
||||
|
|
102
app/js/custom.js
102
app/js/custom.js
|
@ -332,47 +332,42 @@ $('#performupdateModal').on('shown.bs.modal', function (e) {
|
|||
});
|
||||
|
||||
function fetchUpdateResponse() {
|
||||
const xhr = new XMLHttpRequest();
|
||||
const complete = 6;
|
||||
const error = 7;
|
||||
let phpFile = 'ajax/system/sys_read_logfile.php';
|
||||
|
||||
$.ajax({
|
||||
url: phpFile,
|
||||
type: 'GET',
|
||||
success: function(response) {
|
||||
let endPolling = false;
|
||||
success: function(response) {
|
||||
for (let i = 1; i <= 6; i++) {
|
||||
let divId = '#updateStep' + i;
|
||||
if (response.includes(i.toString())) {
|
||||
$(divId).removeClass('invisible');
|
||||
}
|
||||
if (response.includes(complete)) {
|
||||
var successMsg = $('#successMsg').data('message');
|
||||
$('#updateMsg').after('<span class="small">' + successMsg + '</span>');
|
||||
$('#updateMsg').addClass('fa-check');
|
||||
$('#updateMsg').removeClass('invisible');
|
||||
$('#updateStep6').removeClass('invisible');
|
||||
$('#updateSync2').removeClass("fa-spin");
|
||||
$('#updateOk').removeAttr('disabled');
|
||||
endPolling = true;
|
||||
break;
|
||||
} else if (response.includes(error)) {
|
||||
var errorMsg = $('#errorMsg').data('message');
|
||||
$('#updateMsg').after('<span class="small">' + errorMsg + '</span>');
|
||||
$('#updateMsg').addClass('fa-times');
|
||||
$('#updateMsg').removeClass('invisible');
|
||||
$('#updateSync2').removeClass("fa-spin");
|
||||
$('#updateOk').removeAttr('disabled');
|
||||
endPolling = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!endPolling) {
|
||||
// check if the update is complete or if there's an error
|
||||
if (response.includes(complete)) {
|
||||
var successMsg = $('#successMsg').data('message');
|
||||
$('#updateMsg').after('<span class="small">' + successMsg + '</span>');
|
||||
$('#updateMsg').addClass('fa-check');
|
||||
$('#updateMsg').removeClass('invisible');
|
||||
$('#updateStep6').removeClass('invisible');
|
||||
$('#updateSync2').removeClass("fa-spin");
|
||||
$('#updateOk').removeAttr('disabled');
|
||||
} else if (response.includes(error)) {
|
||||
var errorMsg = $('#errorMsg').data('message');
|
||||
$('#updateMsg').after('<span class="small">' + errorMsg + '</span>');
|
||||
$('#updateMsg').addClass('fa-times');
|
||||
$('#updateMsg').removeClass('invisible');
|
||||
$('#updateSync2').removeClass("fa-spin");
|
||||
$('#updateOk').removeAttr('disabled');
|
||||
} else {
|
||||
setTimeout(fetchUpdateResponse, 500);
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error(error);
|
||||
console.error("AJAX Error:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -496,6 +491,7 @@ $('#install-user-plugin').on('shown.bs.modal', function (e) {
|
|||
$('#plugin-license').text(manifestData.license || 'Unknown');
|
||||
$('#plugin-locale').text(manifestData.default_locale || 'Unknown');
|
||||
$('#plugin-configuration').html(formatProperty(manifestData.configuration || 'None'));
|
||||
$('#plugin-packages').html(formatProperty(manifestData.keys || 'None'));
|
||||
$('#plugin-dependencies').html(formatProperty(manifestData.dependencies || 'None'));
|
||||
$('#plugin-javascript').html(formatProperty(manifestData.javascript || 'None'));
|
||||
$('#plugin-sudoers').html(formatProperty(manifestData.sudoers || 'None'));
|
||||
|
@ -994,42 +990,9 @@ function getCookie(cname) {
|
|||
// Define themes
|
||||
var themes = {
|
||||
"default": "custom.php",
|
||||
"hackernews" : "hackernews.css",
|
||||
"lightsout" : "lightsout.php",
|
||||
"material-light" : "material-light.php",
|
||||
"material-dark" : "material-dark.php",
|
||||
"hackernews" : "hackernews.css"
|
||||
}
|
||||
|
||||
// Toggles the sidebar navigation.
|
||||
// Overrides the default SB Admin 2 behavior
|
||||
$("#sidebarToggleTopbar").on('click', function(e) {
|
||||
$("body").toggleClass("sidebar-toggled");
|
||||
$(".sidebar").toggleClass("toggled d-none");
|
||||
});
|
||||
|
||||
// Overrides SB Admin 2
|
||||
$("#sidebarToggle, #sidebarToggleTop").on('click', function(e) {
|
||||
var toggled = $(".sidebar").hasClass("toggled");
|
||||
// Persist state in cookie
|
||||
setCookie('sidebarToggled',toggled, 90);
|
||||
});
|
||||
|
||||
$(function() {
|
||||
if ($(window).width() < 768) {
|
||||
$('.sidebar').addClass('toggled');
|
||||
setCookie('sidebarToggled',false, 90);
|
||||
}
|
||||
});
|
||||
|
||||
$(window).on("load resize",function(e) {
|
||||
if ($(window).width() > 768) {
|
||||
$('.sidebar').removeClass('d-none d-md-block');
|
||||
if (getCookie('sidebarToggled') == 'false') {
|
||||
$('.sidebar').removeClass('toggled');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Adds active class to current nav-item
|
||||
$(window).bind("load", function() {
|
||||
var url = window.location;
|
||||
|
@ -1038,6 +1001,27 @@ $(window).bind("load", function() {
|
|||
}).parent().addClass('active');
|
||||
});
|
||||
|
||||
// Sets focus on a specified tab
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const targetTab = params.get("tab");
|
||||
if (targetTab) {
|
||||
let tabElement = document.querySelector(`[data-bs-toggle="tab"][href="#${targetTab}"]`);
|
||||
if (tabElement) {
|
||||
let tab = new bootstrap.Tab(tabElement);
|
||||
tab.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function disableValidation(form) {
|
||||
form.removeAttribute("novalidate");
|
||||
form.classList.remove("needs-validation");
|
||||
form.querySelectorAll("[required]").forEach(function (field) {
|
||||
field.removeAttribute("required");
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
const $htmlElement = $('html');
|
||||
const $modeswitch = $('#night-mode');
|
||||
|
|
|
@ -4,7 +4,7 @@ ctrl_interface_group=0
|
|||
beacon_int=100
|
||||
auth_algs=1
|
||||
wpa_key_mgmt=WPA-PSK
|
||||
ssid=raspi-webgui
|
||||
ssid=RaspAP
|
||||
channel=1
|
||||
hw_mode=g
|
||||
wpa_passphrase=ChangeMe
|
||||
|
|
66
includes/CSRF.php
Normal file
66
includes/CSRF.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace RaspAP\Tokens;
|
||||
|
||||
class CSRF
|
||||
{
|
||||
protected static ?CSRFTokenizer $instance = null;
|
||||
|
||||
/*
|
||||
* Get the CSRFTokenizer instance (singleton)
|
||||
*
|
||||
* @return CSRFTokenizer
|
||||
*/
|
||||
public static function instance(): CSRFTokenizer
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
self::$instance = new CSRFTokenizer();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public static function token(): string
|
||||
{
|
||||
return self::instance()->getToken();
|
||||
}
|
||||
|
||||
public static function verify(): bool
|
||||
{
|
||||
$token = $_POST['csrf_token'];
|
||||
return self::instance()->csrfValidateRequest() &&
|
||||
self::instance()->CSRFValidate($_POST['csrf_token'] ?? '');
|
||||
}
|
||||
|
||||
public static function metaTag(): string
|
||||
{
|
||||
return self::instance()->CSRFMetaTag();
|
||||
}
|
||||
|
||||
public static function hiddenField(): string
|
||||
{
|
||||
return self::instance()->CSRFTokenFieldTag();
|
||||
}
|
||||
|
||||
public static function handleInvalidToken(): void
|
||||
{
|
||||
self::instance()->handleInvalidCSRFToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a CSRF Request
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateRequest(): bool
|
||||
{
|
||||
return self::instance()->csrfValidateRequest();
|
||||
}
|
||||
}
|
||||
|
||||
if (\RaspAP\Tokens\CSRF::validateRequest()) {
|
||||
if (!\RaspAP\Tokens\CSRF::verify()) {
|
||||
error_log("CSRF verification failed. Token: " . ($_POST['csrf_token'] ?? 'not provided'));
|
||||
\RaspAP\Tokens\CSRF::handleInvalidToken();
|
||||
}
|
||||
}
|
||||
|
|
@ -40,7 +40,6 @@ function DisplayAdBlockConfig()
|
|||
file_put_contents("/tmp/dnsmasq_custom", $_POST['adblock-custom-hosts'].PHP_EOL);
|
||||
system("sudo cp /tmp/dnsmasq_custom " .RASPI_ADBLOCK_LISTPATH .'custom.txt', $return);
|
||||
$config.= 'addn-hosts=' .RASPI_ADBLOCK_LISTPATH .'custom.txt'.PHP_EOL;
|
||||
$custom_enabled = true;
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
|
@ -64,6 +63,13 @@ function DisplayAdBlockConfig()
|
|||
}
|
||||
}
|
||||
|
||||
$custom_list = RASPI_ADBLOCK_LISTPATH . 'custom.txt';
|
||||
$custom_enabled = false;
|
||||
|
||||
if (file_exists($custom_list) && filesize($custom_list) > 0) {
|
||||
$custom_enabled = true;
|
||||
}
|
||||
|
||||
exec('cat '. RASPI_ADBLOCK_CONFIG, $return);
|
||||
$arrConf = ParseConfig($return);
|
||||
if (sizeof($arrConf) > 0) {
|
||||
|
|
|
@ -35,6 +35,8 @@ function DisplayAuthConfig($username)
|
|||
} else {
|
||||
$status->addMessage('Old password does not match', 'danger');
|
||||
}
|
||||
} elseif (isset($_POST['logout'])) {
|
||||
$auth->logout();
|
||||
}
|
||||
|
||||
echo renderTemplate(
|
||||
|
|
|
@ -9,31 +9,13 @@
|
|||
*/
|
||||
spl_autoload_register(function ($class) {
|
||||
|
||||
// project-specific namespace prefix
|
||||
$prefix = '';
|
||||
// base directory where all class files are stored
|
||||
$base_dir = __DIR__ . '/../src/';
|
||||
|
||||
// base directory for the namespace prefix
|
||||
$base_dir = 'src/';
|
||||
// convert the fully qualified class name into a file path
|
||||
$file = $base_dir . str_replace('\\', '/', $class) . '.php';
|
||||
|
||||
// normalize the base directory with a trailing separator
|
||||
$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/';
|
||||
|
||||
// does the class use the namespace prefix?
|
||||
$len = strlen($prefix);
|
||||
if (strncmp($prefix, $class, $len) !== 0) {
|
||||
// no, move to the next registered autoloader
|
||||
return;
|
||||
}
|
||||
|
||||
// get the relative class name
|
||||
$relative_class = substr($class, $len);
|
||||
|
||||
// replace the namespace prefix with the base directory, replace namespace
|
||||
// separators with directory separators in the relative class name, append
|
||||
// with .php
|
||||
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
||||
|
||||
// if the file exists, require it
|
||||
// require the file if it exists
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'functions.php';
|
||||
|
||||
if (csrfValidateRequest() && !CSRFValidate()) {
|
||||
handleInvalidCSRFToken();
|
||||
}
|
|
@ -5,226 +5,170 @@ require_once 'includes/wifi_functions.php';
|
|||
require_once 'includes/functions.php';
|
||||
|
||||
/**
|
||||
* Show dashboard page.
|
||||
* Displays the dashboard
|
||||
*/
|
||||
function DisplayDashboard(&$extraFooterScripts)
|
||||
function DisplayDashboard(&$extraFooterScripts): void
|
||||
{
|
||||
getWifiInterface();
|
||||
// instantiate RaspAP objects
|
||||
$system = new \RaspAP\System\Sysinfo;
|
||||
$dashboard = new \RaspAP\UI\Dashboard;
|
||||
$status = new \RaspAP\Messages\StatusMessage;
|
||||
// Need this check interface name for proper shell execution.
|
||||
if (!preg_match('/^([a-zA-Z0-9]+)$/', $_SESSION['wifi_client_interface'])) {
|
||||
$status->addMessage(_('Interface name invalid.'), 'danger');
|
||||
$status->showMessages();
|
||||
return;
|
||||
}
|
||||
$pluginManager = \RaspAP\Plugins\PluginManager::getInstance();
|
||||
|
||||
if (!function_exists('exec')) {
|
||||
$status->addMessage(_('Required exec function is disabled. Check if exec is not added to php disable_functions.'), 'danger');
|
||||
$status->showMessages();
|
||||
return;
|
||||
}
|
||||
exec('ip a show '.$_SESSION['ap_interface'], $stdoutIp);
|
||||
$stdoutIpAllLinesGlued = implode(" ", $stdoutIp);
|
||||
$stdoutIpWRepeatedSpaces = preg_replace('/\s\s+/', ' ', $stdoutIpAllLinesGlued);
|
||||
// set AP and client interface session vars
|
||||
getWifiInterface();
|
||||
|
||||
preg_match('/link\/ether ([0-9a-f:]+)/i', $stdoutIpWRepeatedSpaces, $matchesMacAddr) || $matchesMacAddr[1] = _('No MAC Address Found');
|
||||
$macAddr = $matchesMacAddr[1];
|
||||
|
||||
$ipv4Addrs = '';
|
||||
$ipv4Netmasks = '';
|
||||
if (!preg_match_all('/inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/([0-3][0-9])/i', $stdoutIpWRepeatedSpaces, $matchesIpv4AddrAndSubnet, PREG_SET_ORDER)) {
|
||||
$ipv4Addrs = _('No IPv4 Address Found');
|
||||
} else {
|
||||
foreach ($matchesIpv4AddrAndSubnet as $inet) {
|
||||
$address = $inet[1];
|
||||
$suffix = (int) $inet[2];
|
||||
$netmask = long2ip(-1 << (32 - $suffix));
|
||||
$ipv4Addrs .= " $address";
|
||||
$ipv4Netmasks .= " $netmask";
|
||||
}
|
||||
$ipv4Addrs = trim($ipv4Addrs);
|
||||
$ipv4Netmasks = trim($ipv4Netmasks);
|
||||
}
|
||||
$ipv4Netmasks = empty($ipv4Netmasks) ? "-" : $ipv4Netmasks;
|
||||
|
||||
$ipv6Addrs = '';
|
||||
if (!preg_match_all('/inet6 ([a-f0-9:]+)/i', $stdoutIpWRepeatedSpaces, $matchesIpv6Addr)) {
|
||||
$ipv6Addrs = _('No IPv6 Address Found');
|
||||
} else {
|
||||
if (isset($matchesIpv6Addr[1])) {
|
||||
$ipv6Addrs = implode(' ', $matchesIpv6Addr[1]);
|
||||
}
|
||||
}
|
||||
|
||||
preg_match('/state (UP|DOWN)/i', $stdoutIpWRepeatedSpaces, $matchesState) || $matchesState[1] = 'unknown';
|
||||
$interfaceState = $matchesState[1];
|
||||
|
||||
// Because of table layout used in the ip output we get the interface statistics directly from
|
||||
// the system. One advantage of this is that it could work when interface is disable.
|
||||
exec('cat /sys/class/net/'.$_SESSION['ap_interface'].'/statistics/rx_packets ', $stdoutCatRxPackets);
|
||||
$strRxPackets = _('No data');
|
||||
if (ctype_digit($stdoutCatRxPackets[0])) {
|
||||
$strRxPackets = $stdoutCatRxPackets[0];
|
||||
}
|
||||
|
||||
exec('cat /sys/class/net/'.$_SESSION['ap_interface'].'/statistics/tx_packets ', $stdoutCatTxPackets);
|
||||
$strTxPackets = _('No data');
|
||||
if (ctype_digit($stdoutCatTxPackets[0])) {
|
||||
$strTxPackets = $stdoutCatTxPackets[0];
|
||||
}
|
||||
|
||||
exec('cat /sys/class/net/'.$_SESSION['ap_interface'].'/statistics/rx_bytes ', $stdoutCatRxBytes);
|
||||
$strRxBytes = _('No data');
|
||||
if (ctype_digit($stdoutCatRxBytes[0])) {
|
||||
$strRxBytes = $stdoutCatRxBytes[0];
|
||||
$strRxBytes .= getHumanReadableDatasize($strRxBytes);
|
||||
}
|
||||
|
||||
exec('cat /sys/class/net/'.$_SESSION['ap_interface'].'/statistics/tx_bytes ', $stdoutCatTxBytes);
|
||||
$strTxBytes = _('No data');
|
||||
if (ctype_digit($stdoutCatTxBytes[0])) {
|
||||
$strTxBytes = $stdoutCatTxBytes[0];
|
||||
$strTxBytes .= getHumanReadableDatasize($strTxBytes);
|
||||
}
|
||||
|
||||
exec ('vnstat --dbiflist', $stdoutVnStatDB);
|
||||
if (!preg_match('/'.$_SESSION['ap_interface'].'/', $stdoutVnStatDB[0])) {
|
||||
exec('sudo vnstat --add --iface '.$_SESSION['ap_interface'], $return);
|
||||
}
|
||||
|
||||
define('SSIDMAXLEN', 32);
|
||||
// Warning iw comes with: "Do NOT screenscrape this tool, we don't consider its output stable."
|
||||
exec('iw dev ' .$_SESSION['wifi_client_interface']. ' link ', $stdoutIw);
|
||||
$stdoutIwAllLinesGlued = implode('+', $stdoutIw); // Break lines with character illegal in SSID and MAC addr
|
||||
$stdoutIwWRepSpaces = preg_replace('/\s\s+/', ' ', $stdoutIwAllLinesGlued);
|
||||
|
||||
preg_match('/Connected to (([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2}))/', $stdoutIwWRepSpaces, $matchesBSSID) || $matchesBSSID[1] = '';
|
||||
$connectedBSSID = $matchesBSSID[1];
|
||||
$connectedBSSID = empty($connectedBSSID) ? "-" : $connectedBSSID;
|
||||
|
||||
$wlanHasLink = false;
|
||||
if ($interfaceState === 'UP') {
|
||||
$wlanHasLink = true;
|
||||
}
|
||||
|
||||
if (!preg_match('/SSID: ([^+]{1,'.SSIDMAXLEN.'})/', $stdoutIwWRepSpaces, $matchesSSID)) {
|
||||
$wlanHasLink = false;
|
||||
$matchesSSID[1] = 'None';
|
||||
}
|
||||
$connectedSSID = str_replace('\x20', '', $matchesSSID[1]);
|
||||
|
||||
preg_match('/freq: (\d+)/i', $stdoutIwWRepSpaces, $matchesFrequency) || $matchesFrequency[1] = '';
|
||||
$frequency = $matchesFrequency[1].' MHz';
|
||||
|
||||
preg_match('/signal: (-?[0-9]+ dBm)/i', $stdoutIwWRepSpaces, $matchesSignal) || $matchesSignal[1] = '';
|
||||
$signalLevel = $matchesSignal[1];
|
||||
$signalLevel = empty($signalLevel) ? "-" : $signalLevel;
|
||||
|
||||
preg_match('/tx bitrate: ([0-9\.]+ [KMGT]?Bit\/s)/', $stdoutIwWRepSpaces, $matchesBitrate) || $matchesBitrate[1] = '';
|
||||
$bitrate = $matchesBitrate[1];
|
||||
$bitrate = empty($bitrate) ? "-" : $bitrate;
|
||||
|
||||
// txpower is now displayed on iw dev(..) info command, not on link command.
|
||||
exec('iw dev '.$_SESSION['wifi_client_interface'].' info ', $stdoutIwInfo);
|
||||
$stdoutIwInfoAllLinesGlued = implode(' ', $stdoutIwInfo);
|
||||
$stdoutIpInfoWRepSpaces = preg_replace('/\s\s+/', ' ', $stdoutIwInfoAllLinesGlued);
|
||||
|
||||
preg_match('/txpower ([0-9\.]+ dBm)/i', $stdoutIpInfoWRepSpaces, $matchesTxPower) || $matchesTxPower[1] = '';
|
||||
$txPower = $matchesTxPower[1];
|
||||
|
||||
// iw does not have the "Link Quality". This is a is an aggregate value,
|
||||
// and depends on the driver and hardware.
|
||||
// Display link quality as signal quality for now.
|
||||
$strLinkQuality = 0;
|
||||
if ($signalLevel > -100 && $wlanHasLink) {
|
||||
if ($signalLevel >= 0) {
|
||||
$strLinkQuality = 100;
|
||||
} else {
|
||||
$strLinkQuality = 100 + intval($signalLevel);
|
||||
}
|
||||
}
|
||||
|
||||
$wlan0up = false;
|
||||
$classMsgDevicestatus = 'warning';
|
||||
if ($interfaceState === 'UP') {
|
||||
$wlan0up = true;
|
||||
$classMsgDevicestatus = 'success';
|
||||
}
|
||||
|
||||
if (!RASPI_MONITOR_ENABLED) {
|
||||
if (isset($_POST['ifdown_wlan0'])) {
|
||||
// Pressed stop button
|
||||
if ($interfaceState === 'UP') {
|
||||
$status->addMessage(sprintf(_('Interface is going %s.'), _('down')), 'warning');
|
||||
exec('sudo ip link set '.$_SESSION['ap_interface'].' down');
|
||||
$wlan0up = false;
|
||||
$status->addMessage(sprintf(_('Interface is now %s.'), _('down')), 'success');
|
||||
} elseif ($interfaceState === 'unknown') {
|
||||
$status->addMessage(_('Interface state unknown.'), 'danger');
|
||||
} else {
|
||||
$status->addMessage(sprintf(_('Interface already %s.'), _('down')), 'warning');
|
||||
}
|
||||
} elseif (isset($_POST['ifup_wlan0'])) {
|
||||
// Pressed start button
|
||||
if ($interfaceState === 'DOWN') {
|
||||
$status->addMessage(sprintf(_('Interface is going %s.'), _('up')), 'warning');
|
||||
exec('sudo ip link set ' .$_SESSION['ap_interface']. ' up');
|
||||
exec('sudo ip -s a f label ' .$_SESSION['ap_interface']);
|
||||
$wlan0up = true;
|
||||
$status->addMessage(sprintf(_('Interface is now %s.'), _('up')), 'success');
|
||||
} elseif ($interfaceState === 'unknown') {
|
||||
$status->addMessage(_('Interface state unknown.'), 'danger');
|
||||
} else {
|
||||
$status->addMessage(sprintf(_('Interface already %s.'), _('up')), 'warning');
|
||||
}
|
||||
} else {
|
||||
$status->addMessage(sprintf(_('Interface is %s.'), strtolower($interfaceState)), $classMsgDevicestatus);
|
||||
}
|
||||
}
|
||||
// brought in from template
|
||||
$arrHostapdConf = parse_ini_file(RASPI_CONFIG.'/hostapd.ini');
|
||||
$bridgedEnable = $arrHostapdConf['BridgedEnable'];
|
||||
$interface = $_SESSION['ap_interface'] ?? 'wlan0';
|
||||
$clientInterface = $_SESSION['wifi_client_interface'];
|
||||
$apInterface = $_SESSION['ap_interface'];
|
||||
$MACPattern = '"([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}"';
|
||||
$hostname = $system->hostname();
|
||||
$revision = $system->rpiRevision();
|
||||
$deviceImage = $dashboard->getDeviceImage($revision);
|
||||
$hostapd = $system->hostapdStatus();
|
||||
$adblock = $system->adBlockStatus();
|
||||
$vpn = $system->getActiveVpnInterface();
|
||||
$frequency = $dashboard->getFrequencyBand($interface);
|
||||
$details = $dashboard->getInterfaceDetails($interface);
|
||||
$wireless = $dashboard->getWirelessDetails($interface);
|
||||
$connectionType = $dashboard->getConnectionType();
|
||||
$connectionIcon = $dashboard->getConnectionIcon($connectionType);
|
||||
$state = strtolower($details['state']);
|
||||
$wirelessClients = $dashboard->getWirelessClients();
|
||||
$ethernetClients = $dashboard->getEthernetClients();
|
||||
$totalClients = $wirelessClients + $ethernetClients;
|
||||
$plugins = $pluginManager->getInstalledPlugins();
|
||||
$bridgedEnable = getBridgedState();
|
||||
|
||||
if (getBridgedState()) {
|
||||
$moreLink = "hostapd_conf";
|
||||
exec('iw dev ' . $apInterface . ' station dump | grep -oE ' . $MACPattern, $clients);
|
||||
} else {
|
||||
$moreLink = "dhcpd_conf";
|
||||
exec('cat ' . RASPI_DNSMASQ_LEASES . '| grep -E $(iw dev ' . $apInterface . ' station dump | grep -oE ' . $MACPattern . ' | paste -sd "|")', $clients);
|
||||
// handle page actions
|
||||
if (!empty($_POST)) {
|
||||
$status = $dashboard->handlePageAction($state, $_POST, $status, $interface);
|
||||
// refresh interface details + state
|
||||
$details = $dashboard->getInterfaceDetails($interface);
|
||||
$state = strtolower($details['state']);
|
||||
}
|
||||
|
||||
$ipv4Address = $details['ipv4'];
|
||||
$ipv4Netmask = $details['ipv4_netmask'];
|
||||
$macAddress = $details['mac'];
|
||||
$ssid = $wireless['ssid'];
|
||||
$ethernetActive = ($connectionType === 'ethernet') ? "active" : "inactive";
|
||||
$wirelessActive = ($connectionType === 'wireless') ? "active" : "inactive";
|
||||
$tetheringActive = ($connectionType === 'tethering') ? "active" : "inactive";
|
||||
$cellularActive = ($connectionType === 'cellular') ? "active" : "inactive";
|
||||
$bridgedStatus = ($bridgedEnable == 1) ? "active" : "";
|
||||
$hostapdStatus = ($hostapd[0] == 1) ? "active" : "";
|
||||
$adblockStatus = ($adblock == true) ? "active" : "";
|
||||
$wirelessClientActive = ($wirelessClients > 0) ? "active" : "inactive";
|
||||
$wirelessClientLabel = sprintf(
|
||||
_('%d WLAN %s'),
|
||||
$wirelessClients,
|
||||
$dashboard->formatClientLabel($wirelessClients)
|
||||
);
|
||||
$ethernetClientActive = ($ethernetClients > 0) ? "active" : "inactive";
|
||||
$ethernetClientLabel = sprintf(
|
||||
_('%d LAN %s'),
|
||||
$ethernetClients,
|
||||
$dashboard->formatClientLabel($ethernetClients)
|
||||
);
|
||||
$totalClientsActive = ($totalClients > 0) ? "active": "inactive";
|
||||
$freq5active = $freq24active = "";
|
||||
$varName = "freq" . str_replace('.', '', $frequency) . "active";
|
||||
$$varName = "active";
|
||||
$vpnStatus = $vpn ? "active" : "inactive";
|
||||
$vpnManaged = $vpn ? $dashboard->getVpnManaged($vpn) : null;
|
||||
$firewallManaged = $firewallStatus = "";
|
||||
$firewallInstalled = array_filter($plugins, fn($p) => str_ends_with($p, 'Firewall')) ? true : false;
|
||||
if (!$firewallInstalled) {
|
||||
$firewallUnavailable = '<i class="fas fa-slash fa-stack-1x"></i>';
|
||||
} else {
|
||||
$firewallManaged = '<a href="/plugin__Firewall">';
|
||||
$firewallStatus = ($dashboard->firewallEnabled() == true) ? "active" : "";
|
||||
}
|
||||
$ifaceStatus = $wlan0up ? "up" : "down";
|
||||
|
||||
echo renderTemplate(
|
||||
"dashboard", compact(
|
||||
"clients",
|
||||
"moreLink",
|
||||
"apInterface",
|
||||
"revision",
|
||||
"deviceImage",
|
||||
"interface",
|
||||
"clientInterface",
|
||||
"ifaceStatus",
|
||||
"bridgedEnable",
|
||||
"status",
|
||||
"ipv4Addrs",
|
||||
"ipv4Netmasks",
|
||||
"ipv6Addrs",
|
||||
"macAddr",
|
||||
"strRxPackets",
|
||||
"strRxBytes",
|
||||
"strTxPackets",
|
||||
"strTxBytes",
|
||||
"connectedSSID",
|
||||
"connectedBSSID",
|
||||
"bitrate",
|
||||
"signalLevel",
|
||||
"txPower",
|
||||
"state",
|
||||
"bridgedStatus",
|
||||
"hostapdStatus",
|
||||
"adblockStatus",
|
||||
"vpnStatus",
|
||||
"vpnManaged",
|
||||
"firewallUnavailable",
|
||||
"firewallStatus",
|
||||
"firewallManaged",
|
||||
"ipv4Address",
|
||||
"ipv4Netmask",
|
||||
"macAddress",
|
||||
"ssid",
|
||||
"frequency",
|
||||
"strLinkQuality",
|
||||
"wlan0up"
|
||||
"freq5active",
|
||||
"freq24active",
|
||||
"wirelessClients",
|
||||
"wirelessClientLabel",
|
||||
"wirelessClientActive",
|
||||
"ethernetClients",
|
||||
"ethernetClientLabel",
|
||||
"ethernetClientActive",
|
||||
"totalClients",
|
||||
"totalClientsActive",
|
||||
"connectionType",
|
||||
"connectionIcon",
|
||||
"ethernetActive",
|
||||
"wirelessActive",
|
||||
"tetheringActive",
|
||||
"cellularActive",
|
||||
"status"
|
||||
)
|
||||
);
|
||||
$extraFooterScripts[] = array('src'=>'app/js/dashboardchart.js', 'defer'=>false);
|
||||
$extraFooterScripts[] = array('src'=>'app/js/linkquality.js', 'defer'=>false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a URL for an svg solid line representing the associated
|
||||
* connection type
|
||||
*
|
||||
* @param string $connectionType
|
||||
* @return string
|
||||
*/
|
||||
function renderConnection(string $connectionType): string
|
||||
{
|
||||
$deviceMap = [
|
||||
'ethernet' => 'device-1',
|
||||
'wireless' => 'device-2',
|
||||
'tethering' => 'device-3',
|
||||
'cellular' => 'device-4'
|
||||
];
|
||||
$device = $deviceMap[$connectionType] ?? 'device-unknown';
|
||||
|
||||
// return generated URL for solid.php
|
||||
return sprintf('app/img/solid.php?joint&%s&out', $device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a URL for an svg solid line representing associated
|
||||
* client connection(s)
|
||||
*
|
||||
* @param int $wirelessClients
|
||||
* @param int $ethernetClients
|
||||
* @return string
|
||||
*/
|
||||
function renderClientConnections(int $wirelessClients, int $ethernetClients): string
|
||||
{
|
||||
$devices = [];
|
||||
|
||||
if ($wirelessClients > 0) {
|
||||
$devices[] = 'device-1&out';
|
||||
}
|
||||
if ($ethernetClients > 0) {
|
||||
$devices[] = 'device-2&out';
|
||||
}
|
||||
return empty($devices) ? '' : sprintf(
|
||||
'<img src="app/img/right-solid.php?%s" class="solid-lines solid-lines-right" alt="Client connections">',
|
||||
implode('&', $devices)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ if (!defined('RASPI_CONFIG')) {
|
|||
$defaults = [
|
||||
'RASPI_BRAND_TEXT' => 'RaspAP',
|
||||
'RASPI_BRAND_TITLE' => RASPI_BRAND_TEXT.' Admin Panel',
|
||||
'RASPI_VERSION' => '3.2.8',
|
||||
'RASPI_VERSION' => '3.3.2',
|
||||
'RASPI_CONFIG_NETWORK' => RASPI_CONFIG.'/networking/defaults.json',
|
||||
'RASPI_CONFIG_PROVIDERS' => 'config/vpn-providers.json',
|
||||
'RASPI_CONFIG_API' => RASPI_CONFIG.'/api',
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
<?php
|
||||
require_once 'src/RaspAP/Exceptions/ExceptionHandler.php';
|
||||
|
||||
$handler = new RaspAP\Exceptions\ExceptionHandler;
|
||||
?>
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
<div class="d-flex align-items-center justify-content-between small">
|
||||
<div class="text-muted">
|
||||
<span class="pe-2"><a href="/about">v<?php echo RASPI_VERSION; ?></a></span> |
|
||||
<span class="ps-2">Created by the <a href="https://github.com/RaspAP" target="_blank" rel="noopener">RaspAP Team</a></span>
|
||||
<span class="ps-2"><?php echo sprintf(_('Created by the <a href="%s" target="_blank" rel="noopener">%s</a>'), 'https://github.com/RaspAP', _('RaspAP Team')); ?></span>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
<i class="fas fa-heart heart"></i> <a href="https://docs.raspap.com/insiders" target="_blank" rel="noopener">Get Insiders</a>
|
||||
<i class="fas fa-heart heart"></i> <a href="https://docs.raspap.com/insiders" target="_blank" rel="noopener"><?php echo _("Get Insiders"); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -177,15 +177,17 @@ function getDefaultNetOpts($svc,$key)
|
|||
* @param string $key
|
||||
* @return object $json
|
||||
*/
|
||||
function getProviderValue($id,$key)
|
||||
function getProviderValue($id, $key)
|
||||
{
|
||||
$obj = json_decode(file_get_contents(RASPI_CONFIG_PROVIDERS), true);
|
||||
if ($obj === null) {
|
||||
if (!isset($obj['providers']) || !is_array($obj['providers'])) {
|
||||
return false;
|
||||
} else {
|
||||
$id--;
|
||||
return $obj['providers'][$id][$key];
|
||||
}
|
||||
$id--;
|
||||
if (!isset($obj['providers'][$id]) || !is_array($obj['providers'][$id])) {
|
||||
return false;
|
||||
}
|
||||
return $obj['providers'][$id][$key] ?? false;
|
||||
}
|
||||
|
||||
/* Functions to write ini files */
|
||||
|
@ -304,82 +306,6 @@ function filter_comments($var)
|
|||
return $var[0] != '#';
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a CSRF token in the session
|
||||
*/
|
||||
function ensureCSRFSessionToken()
|
||||
{
|
||||
if (empty($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add CSRF Token to form
|
||||
*/
|
||||
function CSRFTokenFieldTag()
|
||||
{
|
||||
$token = htmlspecialchars($_SESSION['csrf_token']);
|
||||
return '<input type="hidden" name="csrf_token" value="' . $token . '">';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retuns a CSRF meta tag (for use with xhr, for example)
|
||||
*/
|
||||
function CSRFMetaTag()
|
||||
{
|
||||
$token = htmlspecialchars($_SESSION['csrf_token']);
|
||||
return '<meta name="csrf_token" content="' . $token . '">';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate CSRF Token
|
||||
*/
|
||||
function CSRFValidate()
|
||||
{
|
||||
if (empty($_SESSION['csrf_token']) || !is_string($_SESSION['csrf_token'])) {
|
||||
error_log('Session expired or CSRF token is missing.');
|
||||
header('Location: /login');
|
||||
exit;
|
||||
}
|
||||
|
||||
$post_token = $_POST['csrf_token'] ?? null;
|
||||
$header_token = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
|
||||
|
||||
if (empty($post_token) && is_null($header_token)) {
|
||||
error_log('CSRF token missing in the request');
|
||||
return false;
|
||||
}
|
||||
$request_token = $post_token ?: $header_token;
|
||||
|
||||
if (hash_equals($_SESSION['csrf_token'], $request_token)) {
|
||||
return true;
|
||||
} else {
|
||||
error_log('CSRF token mismatch');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the request be CSRF-validated?
|
||||
*/
|
||||
function csrfValidateRequest()
|
||||
{
|
||||
$request_method = strtolower($_SERVER['REQUEST_METHOD']);
|
||||
return in_array($request_method, [ "post", "put", "patch", "delete" ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle invalid CSRF
|
||||
*/
|
||||
function handleInvalidCSRFToken()
|
||||
{
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
header('Content-Type: text/plain');
|
||||
echo 'Invalid CSRF token';
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether array is associative
|
||||
*/
|
||||
|
@ -711,7 +637,6 @@ function formatDateAgo($datetime, $full = false)
|
|||
function initializeApp()
|
||||
{
|
||||
$_SESSION["theme_url"] = getThemeOpt();
|
||||
$_SESSION["toggleState"] = getSidebarState();
|
||||
$_SESSION["bridgedEnabled"] = getBridgedState();
|
||||
$_SESSION["providerID"] = getProviderID();
|
||||
}
|
||||
|
@ -737,22 +662,17 @@ function getColorOpt()
|
|||
return $color;
|
||||
}
|
||||
|
||||
function getSidebarState()
|
||||
{
|
||||
if(isset($_COOKIE['sidebarToggled'])) {
|
||||
if ($_COOKIE['sidebarToggled'] == 'true' ) {
|
||||
return "toggled";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns bridged AP mode status
|
||||
function getBridgedState()
|
||||
{
|
||||
$arrHostapdConf = parse_ini_file(RASPI_CONFIG.'/hostapd.ini');
|
||||
// defaults to false
|
||||
|
||||
$hostapdIni = RASPI_CONFIG . '/hostapd.ini';
|
||||
if (!file_exists($hostapdIni)) {
|
||||
return 0;
|
||||
} else {
|
||||
$arrHostapdConf = parse_ini_file($hostapdIni);
|
||||
}
|
||||
return $arrHostapdConf['BridgedEnable'];
|
||||
}
|
||||
}
|
||||
|
||||
// Returns VPN provider ID, if defined
|
||||
function getProviderID()
|
||||
|
|
|
@ -19,7 +19,7 @@ function DisplayHostAPDConfig()
|
|||
'a' => '802.11a - 5 GHz',
|
||||
'b' => '802.11b - 2.4 GHz',
|
||||
'g' => '802.11g - 2.4 GHz',
|
||||
'n' => '802.11n - 2.4 GHz',
|
||||
'n' => '802.11n - 2.4/5 GHz',
|
||||
'ac' => '802.11ac - 5 GHz'
|
||||
];
|
||||
$languageCode = strtok($_SESSION['locale'], '_');
|
||||
|
@ -46,7 +46,12 @@ function DisplayHostAPDConfig()
|
|||
SaveHostAPDConfig($arrSecurity, $arrEncType, $arr80211Standard, $interfaces, $reg_domain, $status);
|
||||
}
|
||||
}
|
||||
$arrHostapdConf = parse_ini_file(RASPI_CONFIG.'/hostapd.ini');
|
||||
|
||||
$arrHostapdConf = [];
|
||||
$hostapdIni = RASPI_CONFIG . '/hostapd.ini';
|
||||
if (file_exists($hostapdIni)) {
|
||||
$arrHostapdConf = parse_ini_file($hostapdIni);
|
||||
}
|
||||
|
||||
if (!RASPI_MONITOR_ENABLED) {
|
||||
if (isset($_POST['StartHotspot']) || isset($_POST['RestartHotspot'])) {
|
||||
|
@ -136,6 +141,9 @@ function DisplayHostAPDConfig()
|
|||
}
|
||||
}
|
||||
|
||||
$arrConfig['ignore_broadcast_ssid'] ??= 0;
|
||||
$arrConfig['max_num_sta'] ??= 0;
|
||||
$arrConfig['wep_default_key'] ??= 0;
|
||||
exec('sudo /bin/chmod o+r '.RASPI_HOSTAPD_LOG);
|
||||
$logdata = getLogLimited(RASPI_HOSTAPD_LOG);
|
||||
|
||||
|
@ -281,18 +289,13 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $reg_dom
|
|||
$good_input = false;
|
||||
}
|
||||
|
||||
if (isset($_POST['hiddenSSID'])) {
|
||||
if (!is_int((int)$_POST['hiddenSSID'])) {
|
||||
$status->addMessage('Parameter hiddenSSID not a number.', 'danger');
|
||||
$good_input = false;
|
||||
} elseif ((int)$_POST['hiddenSSID'] < 0 || (int)$_POST['hiddenSSID'] >= 3) {
|
||||
$status->addMessage('Parameter hiddenSSID contains invalid configuratie value.', 'danger');
|
||||
$good_input = false;
|
||||
} else {
|
||||
$ignore_broadcast_ssid = $_POST['hiddenSSID'];
|
||||
}
|
||||
} else {
|
||||
$ignore_broadcast_ssid = '0';
|
||||
$ignore_broadcast_ssid = $_POST['hiddenSSID'] ?? '0';
|
||||
if (!ctype_digit($ignore_broadcast_ssid)) {
|
||||
$status->addMessage('Parameter hiddenSSID not a number.', 'danger');
|
||||
$good_input = false;
|
||||
} elseif ((int)$ignore_broadcast_ssid < 0 || (int)$ignore_broadcast_ssid >= 3) {
|
||||
$status->addMessage('Parameter hiddenSSID contains an invalid configuration value.', 'danger');
|
||||
$good_input = false;
|
||||
}
|
||||
|
||||
if (! in_array($_POST['interface'], $interfaces)) {
|
||||
|
@ -364,14 +367,17 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $reg_dom
|
|||
|
||||
// Set dhcp values from system config, fallback to default if undefined
|
||||
$jsonData = json_decode(getNetConfig($ap_iface), true);
|
||||
$ip_address = ($jsonData['StaticIP'] == '') ? getDefaultNetValue('dhcp',$ap_iface,'static ip_address') : $jsonData['StaticIP'];
|
||||
$domain_name_server = ($jsonData['StaticDNS'] =='') ? getDefaultNetValue('dhcp',$ap_iface,'static domain_name_server') : $jsonData['StaticDNS'];
|
||||
$routers = ($jsonData['StaticRouters'] == '') ? getDefaultNetValue('dhcp',$ap_iface,'static routers') : $jsonData['StaticRouters'];
|
||||
$netmask = ($jsonData['SubnetMask'] == '' || $jsonData['SubnetMask'] == '0.0.0.0') ? getDefaultNetValue('dhcp',$ap_iface,'subnetmask') : $jsonData['SubnetMask'];
|
||||
$ip_address = empty($jsonData['StaticIP'])
|
||||
? getDefaultNetValue('dhcp', $ap_iface, 'static ip_address') : $jsonData['StaticIP'];
|
||||
$domain_name_server = empty($jsonData['StaticDNS'])
|
||||
? getDefaultNetValue('dhcp', $ap_iface, 'static domain_name_server') : $jsonData['StaticDNS'];
|
||||
$routers = empty($jsonData['StaticRouters'])
|
||||
? getDefaultNetValue('dhcp', $ap_iface, 'static routers') : $jsonData['StaticRouters'];
|
||||
$netmask = (empty($jsonData['SubnetMask']) || $jsonData['SubnetMask'] === '0.0.0.0')
|
||||
? getDefaultNetValue('dhcp', $ap_iface, 'subnetmask') : $jsonData['SubnetMask'];
|
||||
if (isset($ip_address) && !preg_match('/.*\/\d+/', $ip_address)) {
|
||||
$ip_address.='/'.mask2cidr($netmask);
|
||||
}
|
||||
|
||||
if ($bridgedEnable == 1) {
|
||||
$config = array_keys(getDefaultNetOpts('dhcp','options'));
|
||||
$config[] = PHP_EOL.'# RaspAP br0 configuration';
|
||||
|
@ -392,7 +398,9 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $reg_dom
|
|||
$config[] = 'static ip_address='.$ip_address;
|
||||
$config[] = 'static routers='.$routers;
|
||||
$config[] = 'static domain_name_server='.$domain_name_server;
|
||||
if (! is_null($jsonData['Metric'])) { $config[] = 'metric '.$jsonData['Metric']; }
|
||||
if (!empty($jsonData['Metric'])) {
|
||||
$config[] = 'metric ' . $jsonData['Metric'];
|
||||
}
|
||||
}
|
||||
$dhcp_cfg = file_get_contents(RASPI_DHCPCD_CONFIG);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*
|
||||
* Refer to: https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
|
||||
*/
|
||||
if (empty($_SESSION['locale']) && strlen($_SERVER['HTTP_ACCEPT_LANGUAGE']) >= 2) {
|
||||
if (empty($_SESSION['locale']) && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) && strlen($_SERVER['HTTP_ACCEPT_LANGUAGE']) >= 2) {
|
||||
$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
|
||||
switch ($lang) {
|
||||
case "de":
|
||||
|
@ -90,9 +90,10 @@ if (empty($_SESSION['locale']) && strlen($_SERVER['HTTP_ACCEPT_LANGUAGE']) >= 2)
|
|||
// Use: 'sudo raspi-configure' and select 'Localisation Options'
|
||||
|
||||
// activate the locale setting
|
||||
putenv("LANG=" . $_SESSION['locale']);
|
||||
setlocale(LC_ALL, $_SESSION['locale']);
|
||||
|
||||
if (!empty($_SESSION['locale'])) {
|
||||
putenv("LANG=" . $_SESSION['locale']);
|
||||
setlocale(LC_ALL, $_SESSION['locale']);
|
||||
}
|
||||
bindtextdomain(LOCALE_DOMAIN, LOCALE_ROOT);
|
||||
bind_textdomain_codeset(LOCALE_DOMAIN, 'UTF-8');
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<!-- Auth user -->
|
||||
<li class="nav-item mt-1">
|
||||
<a class="nav-link" href="auth_conf">
|
||||
<span class="mr-2 small nav-user"><?php echo htmlspecialchars($_SESSION['user_id'], ENT_QUOTES); ?></span>
|
||||
<span class="mr-2 small nav-user"><?php echo htmlspecialchars($_SESSION['user_id'] ?? '', ENT_QUOTES); ?></span>
|
||||
<i class="fas fa-user-circle text-muted mt-2 fa-3x"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -50,6 +50,6 @@ if ($hostapd[0] ==1) {
|
|||
$hostapd_led = "service-status-up";
|
||||
} else {
|
||||
$hostapd_status = "down";
|
||||
$hostapd_led = "service-status-down";
|
||||
$hostapd_led = "service-status-warn";
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ require_once 'config.php';
|
|||
function DisplaySystem(&$extraFooterScripts)
|
||||
{
|
||||
$status = new \RaspAP\Messages\StatusMessage;
|
||||
$dashboard = new \RaspAP\UI\Dashboard;
|
||||
$pluginInstaller = \RaspAP\Plugins\PluginInstaller::getInstance();
|
||||
|
||||
if (isset($_POST['SaveLanguage'])) {
|
||||
|
@ -86,6 +87,7 @@ function DisplaySystem(&$extraFooterScripts)
|
|||
$kernel = $system->kernelVersion();
|
||||
$systime = $system->systime();
|
||||
$revision = $system->rpiRevision();
|
||||
$deviceImage = $dashboard->getDeviceImage($revision);
|
||||
|
||||
// memory use
|
||||
$memused = $system->usedMemory();
|
||||
|
@ -129,6 +131,7 @@ function DisplaySystem(&$extraFooterScripts)
|
|||
"uptime",
|
||||
"systime",
|
||||
"revision",
|
||||
"deviceImage",
|
||||
"cores",
|
||||
"os",
|
||||
"kernel",
|
||||
|
|
|
@ -160,19 +160,20 @@ function sortNetworksByRSSI(&$networks)
|
|||
*/
|
||||
function getWifiInterface()
|
||||
{
|
||||
$arrHostapdConf = parse_ini_file(RASPI_CONFIG.'/hostapd.ini');
|
||||
$iface = $_SESSION['ap_interface'] = isset($arrHostapdConf['WifiInterface']) ? $arrHostapdConf['WifiInterface'] : RASPI_WIFI_AP_INTERFACE;
|
||||
// check for 2nd wifi interface -> wifi client on different interface
|
||||
exec("iw dev | awk '$1==\"Interface\" && $2!=\"$iface\" {print $2}'",$iface2);
|
||||
$client_iface = $_SESSION['wifi_client_interface'] = (empty($iface2) ? $iface : trim($iface2[0]));
|
||||
$hostapdIni = RASPI_CONFIG . '/hostapd.ini';
|
||||
$arrHostapdConf = file_exists($hostapdIni) ? parse_ini_file($hostapdIni) : [];
|
||||
|
||||
// specifically for rpi0W in AP-STA mode, the above check ends up with the interfaces
|
||||
// crossed over (wifi_client_interface vs 'ap_interface'), because the second interface (uap0) is
|
||||
// created by raspap and used as the access point.
|
||||
if ($client_iface == "uap0" && ($arrHostapdConf['WifiAPEnable'] ?? 0)){
|
||||
$_SESSION['wifi_client_interface'] = $iface;
|
||||
$_SESSION['ap_interface'] = $client_iface;
|
||||
}
|
||||
$iface = $_SESSION['ap_interface'] = $arrHostapdConf['WifiInterface'] ?? RASPI_WIFI_AP_INTERFACE;
|
||||
|
||||
// check for 2nd wifi interface -> wifi client on different interface
|
||||
exec("iw dev | awk '$1==\"Interface\" && $2!=\"$iface\" {print $2}'", $iface2);
|
||||
$client_iface = $_SESSION['wifi_client_interface'] = empty($iface2) ? $iface : trim($iface2[0]);
|
||||
|
||||
// handle special case for RPi Zero W in AP-STA mode
|
||||
if ($client_iface === "uap0" && ($arrHostapdConf['WifiAPEnable'] ?? 0)) {
|
||||
$_SESSION['wifi_client_interface'] = $iface;
|
||||
$_SESSION['ap_interface'] = $client_iface;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,10 +10,10 @@ function DisplayWireGuardConfig()
|
|||
$status = new \RaspAP\Messages\StatusMessage;
|
||||
$parseFlag = true;
|
||||
if (!RASPI_MONITOR_ENABLED) {
|
||||
$optRules = $_POST['wgRules'];
|
||||
$optConf = $_POST['wgCnfOpt'];
|
||||
$optSrvEnable = $_POST['wgSrvEnable'];
|
||||
$optLogEnable = $_POST['wgLogEnable'];
|
||||
$optRules = isset($_POST['wgRules']) ? $_POST['wgRules'] : null;
|
||||
$optConf = isset($_POST['wgCnfOpt']) ? $_POST['wgCnfOpt'] : null;
|
||||
$optSrvEnable = isset($_POST['wgSrvEnable']) ? $_POST['wgSrvEnable'] : null;
|
||||
$optLogEnable = isset($_POST['wgLogEnable']) ? $_POST['wgLogEnable'] : null;
|
||||
if (isset($_POST['savewgsettings']) && $optConf == 'manual' && $optSrvEnable == 1 ) {
|
||||
SaveWireGuardConfig($status);
|
||||
} elseif (isset($_POST['savewgsettings']) && $optConf == 'upload' && is_uploaded_file($_FILES["wgFile"]["tmp_name"])) {
|
||||
|
@ -69,6 +69,14 @@ function DisplayWireGuardConfig()
|
|||
$wg_state = ($wgstatus[0] == 'active' ? true : false );
|
||||
$public_ip = get_public_ip();
|
||||
|
||||
// retrieve wg log
|
||||
$wg_log = "";
|
||||
if (file_exists('/tmp/wireguard.log')) {
|
||||
exec('sudo chmod o+r /tmp/wireguard.log');
|
||||
$wg_log = file_get_contents('/tmp/wireguard.log');
|
||||
}
|
||||
$peer_id = $peer_id ?? "1";
|
||||
|
||||
echo renderTemplate(
|
||||
"wireguard", compact(
|
||||
"status",
|
||||
|
@ -89,7 +97,8 @@ function DisplayWireGuardConfig()
|
|||
"wg_peerpubkey",
|
||||
"wg_pendpoint",
|
||||
"wg_pallowedips",
|
||||
"wg_pkeepalive"
|
||||
"wg_pkeepalive",
|
||||
"wg_log"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
15
index.php
15
index.php
|
@ -8,13 +8,13 @@
|
|||
* Recommended distribution is Raspberry Pi OS (64-bit) Lite. Specific instructions to install the supported software are
|
||||
* in the README and original post by @SirLagz. For a quick run through, the packages required for the WebGUI are:
|
||||
* lighttpd (version 1.4.69 installed via apt)
|
||||
* php-cgi (version 8.2.26 installed via apt)
|
||||
* php-cgi (version 8.2.28 installed via apt)
|
||||
* along with their supporting packages, php8.2 will also need to be enabled.
|
||||
*
|
||||
* @author Lawrence Yau <sirlagz@gmail.com>
|
||||
* @author Bill Zimmerman <billzimmerman@gmail.com>
|
||||
* @license GNU General Public License, version 3 (GPL-3.0)
|
||||
* @version 3.2.8
|
||||
* @version 3.3.2
|
||||
* @link https://github.com/RaspAP/raspap-webgui/
|
||||
* @link https://raspap.com/
|
||||
* @see http://sirlagz.net/2013/02/08/raspap-webgui/
|
||||
|
@ -23,13 +23,12 @@
|
|||
* as you leave these references intact in the header comments of your source files.
|
||||
*/
|
||||
|
||||
require 'includes/session.php';
|
||||
require 'includes/csrf.php';
|
||||
ensureCSRFSessionToken();
|
||||
|
||||
require_once 'includes/exceptions.php';
|
||||
require_once 'includes/config.php';
|
||||
require_once 'includes/autoload.php';
|
||||
$handler = new RaspAP\Exceptions\ExceptionHandler;
|
||||
|
||||
require_once 'includes/CSRF.php';
|
||||
require_once 'includes/session.php';
|
||||
require_once 'includes/defaults.php';
|
||||
require_once 'includes/locale.php';
|
||||
require_once 'includes/functions.php';
|
||||
|
@ -59,7 +58,7 @@ initializeApp();
|
|||
<html lang="en" <?php setTheme();?>>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<?php echo CSRFMetaTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::metaTag(); ?>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||
<meta name="description" content="">
|
||||
|
|
|
@ -318,7 +318,7 @@ function _create_hostapd_scripts() {
|
|||
# Generate plugin helper scripts
|
||||
function _create_plugin_scripts() {
|
||||
_install_log "Creating plugin helper scripts"
|
||||
sudo mkdir $raspap_dir/plugins || _install_status 1 "Unable to create directory '$raspap_dir/plugins'"
|
||||
sudo mkdir -p $raspap_dir/plugins || _install_status 1 "Unable to create directory '$raspap_dir/plugins'"
|
||||
|
||||
# Copy plugin helper script
|
||||
sudo cp "$webroot_dir/installers/"plugin_helper.sh "$raspap_dir/plugins" || _install_status 1 "Unable to move plugin script"
|
||||
|
@ -600,6 +600,7 @@ function _download_latest_files() {
|
|||
if [ -n "$username" ] && [ -n "$acctoken" ]; then
|
||||
insiders_source_url="https://${username}:${acctoken}@github.com/$repo"
|
||||
git clone --branch $branch --depth 1 --recurse-submodules -c advice.detachedHead=false $insiders_source_url $source_dir || clone=false
|
||||
git -C $source_dir submodule update --remote plugins || clone=false
|
||||
else
|
||||
_install_status 3
|
||||
echo "Insiders please read this: https://docs.raspap.com/insiders/#authentication"
|
||||
|
@ -607,6 +608,7 @@ function _download_latest_files() {
|
|||
fi
|
||||
if [ -z "$insiders_source_url" ]; then
|
||||
git clone --branch $branch --depth 1 --recurse-submodules -c advice.detachedHead=false $git_source_url $source_dir || clone=false
|
||||
git -C $source_dir submodule update --remote plugins || clone=false
|
||||
fi
|
||||
if [ "$clone" = false ]; then
|
||||
_install_status 1 "Unable to download files from GitHub"
|
||||
|
|
|
@ -46,7 +46,7 @@ case "$action" in
|
|||
|
||||
username=$1
|
||||
password=$2
|
||||
|
||||
|
||||
if id "$username" &>/dev/null; then # user already exists
|
||||
echo "OK"
|
||||
exit 0
|
||||
|
@ -122,16 +122,50 @@ case "$action" in
|
|||
echo "OK"
|
||||
;;
|
||||
|
||||
"keys")
|
||||
[ $# -ne 4 ] && { echo "Usage: $0 keys <key_url> <keyring> <repo> <sources>"; exit 1; }
|
||||
|
||||
key_url="$1"
|
||||
keyring="$2"
|
||||
repo="$3"
|
||||
list_file="$4"
|
||||
|
||||
# add repository GPG key if it doesn't already exist
|
||||
if [ ! -f "$keyring" ]; then
|
||||
echo "Downloading GPG key from $key_url..."
|
||||
curl -fsSL "$key_url" | sudo tee "$keyring" > /dev/null || { echo "Error: Failed to download GPG key."; exit 1; }
|
||||
else
|
||||
echo "Repository GPG key already exists at $keyring"
|
||||
fi
|
||||
|
||||
# add repository list if not present
|
||||
if [ ! -f "$list_file" ]; then
|
||||
echo "Adding repository $repo to sources list"
|
||||
curl -fsSL "$repo" | sudo tee "$list_file" > /dev/null || { echo "Error: Failed to add repository to sources list."; exit 1; }
|
||||
update_required=1
|
||||
else
|
||||
echo "Repository already exists in sources list"
|
||||
fi
|
||||
|
||||
# update apt package list if required
|
||||
if [ "$update_required" == "1" ]; then
|
||||
sudo apt-get update || { echo "Error: Failed to update apt"; exit 1; }
|
||||
fi
|
||||
|
||||
echo "OK"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Invalid action: $action"
|
||||
echo "Usage: $0 <action> [parameters...]"
|
||||
echo "Actions:"
|
||||
echo " sudoers <file> Install a sudoers file"
|
||||
echo " packages <packages> Install aptitude package(s)"
|
||||
echo " user <name> <password> Add user non-interactively"
|
||||
echo " config <source <destination> Applies a config file"
|
||||
echo " javascript <source> <destination> Applies a JavaScript file"
|
||||
echo " plugin <source <destination> Copies a plugin directory"
|
||||
echo " sudoers <file> Install a sudoers file"
|
||||
echo " packages <packages> Install aptitude package(s)"
|
||||
echo " user <name> <password> Add user non-interactively"
|
||||
echo " config <source <destination> Applies a config file"
|
||||
echo " javascript <source> <destination> Applies a JavaScript file"
|
||||
echo " plugin <source> <destination> Copies a plugin directory"
|
||||
echo " keys <key_url> <keyring> <repo> <sources> Installs a GPG key for a third-party repo"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
Binary file not shown.
|
@ -25,8 +25,8 @@ msgstr "RaspAP Wifi Configuration Portal"
|
|||
msgid "Toggle navigation"
|
||||
msgstr "Toggle navigation"
|
||||
|
||||
msgid "RaspAP Wifi Portal"
|
||||
msgstr "RaspAP Wifi Portal"
|
||||
msgid "RaspAP Admin Panel"
|
||||
msgstr "RaspAP Admin Panel"
|
||||
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashboard"
|
||||
|
@ -244,8 +244,8 @@ msgstr "Frequency"
|
|||
msgid "Link Quality"
|
||||
msgstr "Link Quality"
|
||||
|
||||
msgid "Information provided by ip and iw and from system"
|
||||
msgstr "Information provided by ip and iw and from system"
|
||||
msgid "Information provided by raspap.system"
|
||||
msgstr "Information provided by raspap.system"
|
||||
|
||||
msgid "No MAC Address Found"
|
||||
msgstr "No MAC Address Found"
|
||||
|
@ -283,9 +283,53 @@ msgstr "Connected Devices"
|
|||
msgid "Client: Ethernet cable"
|
||||
msgstr "Client: Ethernet cable"
|
||||
|
||||
msgid "Current status"
|
||||
msgstr "Current status"
|
||||
|
||||
msgid "Ethernet"
|
||||
msgstr "Ethernet"
|
||||
|
||||
msgid "Repeater"
|
||||
msgstr "Repeater"
|
||||
|
||||
msgid "Tethering"
|
||||
msgstr "Tethering"
|
||||
|
||||
msgid "Cellular"
|
||||
msgstr "Cellular"
|
||||
|
||||
msgid "AP"
|
||||
msgstr "AP"
|
||||
|
||||
msgid "Bridged"
|
||||
msgstr "Bridged"
|
||||
|
||||
msgid "Adblock"
|
||||
msgstr "Adblock"
|
||||
|
||||
msgid "VPN"
|
||||
msgstr "VPN"
|
||||
|
||||
msgid "Firewall"
|
||||
msgstr "Firewall"
|
||||
|
||||
msgid "Netmask"
|
||||
msgstr "Netmask"
|
||||
|
||||
msgid "5G"
|
||||
msgstr "5G"
|
||||
|
||||
msgid "2.4G"
|
||||
msgstr "2.4G"
|
||||
|
||||
msgid "%d WLAN %s"
|
||||
msgstr "%d WLAN %s"
|
||||
|
||||
msgid "client"
|
||||
msgid_plural "clients"
|
||||
msgstr[0] "client"
|
||||
msgstr[1] "clients"
|
||||
|
||||
msgid "Client: Smartphone (USB tethering)"
|
||||
msgstr "Client: Smartphone (USB tethering)"
|
||||
|
||||
|
@ -334,6 +378,16 @@ msgstr "Signal strength"
|
|||
msgid "No Client device or not yet configured"
|
||||
msgstr "No Client device or not yet configured"
|
||||
|
||||
#: includes/footer.php
|
||||
msgid "Created by the <a href=\"%s\" target=\"_blank\" rel=\"noopener\">%s</a>"
|
||||
msgstr "Created by the <a href=\"%s\" target=\"_blank\" rel=\"noopener\">%s</a>"
|
||||
|
||||
msgid "RaspAP Team"
|
||||
msgstr "RaspAP Team"
|
||||
|
||||
msgid "Get Insiders"
|
||||
msgstr "Get Insiders"
|
||||
|
||||
#: includes/dhcp.php
|
||||
msgid "DHCP server settings"
|
||||
msgstr "DHCP server settings"
|
||||
|
|
2
plugins
2
plugins
|
@ -1 +1 @@
|
|||
Subproject commit 825f74edf49ae34705deb4625d3f3c571dc69bda
|
||||
Subproject commit 38331709b6c8198c0dbf1c7c85cb52b8ae3ea79a
|
|
@ -74,6 +74,21 @@ class HTTPAuth
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Logs out the administrative user
|
||||
*/
|
||||
public function logout(): void
|
||||
{
|
||||
session_regenerate_id(true); // generate a new session id
|
||||
session_unset(); // unset all session variables
|
||||
session_destroy(); // destroy the session
|
||||
$redirectUrl = $_SERVER['REQUEST_URI'];
|
||||
if (strpos($redirectUrl, '/login') === false) {
|
||||
header('Location: /login?action=' . urlencode($redirectUrl));
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the current authentication config
|
||||
* return array $config
|
||||
|
|
|
@ -37,7 +37,7 @@ class DotEnv
|
|||
}
|
||||
}
|
||||
} else {
|
||||
throw new Exception(".env file '{$this->envFile}' not found.");
|
||||
throw new \Exception(".env file '{$this->envFile}' not found.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class DotEnv
|
|||
file_put_contents("/tmp/.env", $content);
|
||||
system('sudo mv /tmp/.env '.$this->envFile, $result);
|
||||
if ($result !== 0) {
|
||||
throw new Exception("Unable to move .env file: ". $this->envFile);
|
||||
throw new \Exception("Unable to move .env file: ". $this->envFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ class DotEnv
|
|||
{
|
||||
exec('sudo touch '. escapeshellarg($this->envFile), $output, $result);
|
||||
if ($result !== 0) {
|
||||
throw new Exception("Unable to create .env file: ". $this->envFile);
|
||||
throw new \Exception("Unable to create .env file: ". $this->envFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ class PluginInstaller
|
|||
private $rootPath;
|
||||
private $pluginsManifest;
|
||||
private $repoPublic;
|
||||
private $helperScriptPath;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -34,6 +35,7 @@ class PluginInstaller
|
|||
$this->rootPath = $_SERVER['DOCUMENT_ROOT'];
|
||||
$this->pluginsManifest = '/plugins/manifest.json';
|
||||
$this->repoPublic = $this->getRepository();
|
||||
$this->helperScriptPath = RASPI_CONFIG.'/plugins/plugin_helper.sh';
|
||||
}
|
||||
|
||||
// Returns a single instance of PluginInstaller
|
||||
|
@ -78,7 +80,7 @@ class PluginInstaller
|
|||
|
||||
if (!empty($plugin['namespace'])) {
|
||||
foreach ($installedPlugins as $installedPlugin) {
|
||||
if (str_contains($installedPlugin['class'], $plugin['namespace'])) {
|
||||
if (strpos($installedPlugin['class'], $plugin['namespace']) !== false) {
|
||||
$installed = true;
|
||||
break;
|
||||
}
|
||||
|
@ -187,6 +189,10 @@ class PluginInstaller
|
|||
$this->addSudoers($manifest['sudoers']);
|
||||
$rollbackStack[] = 'removeSudoers';
|
||||
}
|
||||
if (!empty($manifest['keys'])) {
|
||||
$this->installRepositoryKeys($manifest['keys']);
|
||||
$rollbackStack[] = 'uninstallRepositoryKeys';
|
||||
}
|
||||
if (!empty($manifest['dependencies'])) {
|
||||
$this->installDependencies($manifest['dependencies']);
|
||||
$rollbackStack[] = 'uninstallDependencies';
|
||||
|
@ -207,7 +213,6 @@ class PluginInstaller
|
|||
$this->copyPluginFiles($pluginDir, $this->rootPath);
|
||||
$rollbackStack[] = 'removePluginFiles';
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Installation step failed: ' . $e->getMessage());
|
||||
|
@ -243,7 +248,7 @@ class PluginInstaller
|
|||
$cmd = sprintf('sudo visudo -cf %s', escapeshellarg($tmpSudoers));
|
||||
$return = shell_exec($cmd);
|
||||
if (strpos(strtolower($return), 'parsed ok') !== false) {
|
||||
$cmd = sprintf('sudo /etc/raspap/plugins/plugin_helper.sh sudoers %s', escapeshellarg($tmpSudoers));
|
||||
$cmd = sprintf('sudo %s sudoers %s', escapeshellarg($this->helperScriptPath), escapeshellarg($tmpSudoers));
|
||||
$return = shell_exec($cmd);
|
||||
if (strpos(strtolower($return), 'ok') === false) {
|
||||
throw new \Exception('Plugin helper failed to install sudoers.');
|
||||
|
@ -263,7 +268,7 @@ class PluginInstaller
|
|||
$packages = array_keys($dependencies);
|
||||
$packageList = implode(' ', $packages);
|
||||
|
||||
$cmd = sprintf('sudo /etc/raspap/plugins/plugin_helper.sh packages %s', escapeshellarg($packageList));
|
||||
$cmd = sprintf('sudo %s packages %s', escapeshellarg($this->helperScriptPath), escapeshellarg($packageList));
|
||||
$return = shell_exec($cmd);
|
||||
if (strpos(strtolower($return), 'ok') === false) {
|
||||
throw new \Exception('Plugin helper failed to install depedencies.');
|
||||
|
@ -283,7 +288,7 @@ class PluginInstaller
|
|||
$username = escapeshellarg($user['name']);
|
||||
$password = escapeshellarg($user['pass']);
|
||||
|
||||
$cmd = sprintf('sudo /etc/raspap/plugins/plugin_helper.sh user %s %s', $username, $password);
|
||||
$cmd = sprintf('sudo %s user %s %s', escapeshellarg($this->helperScriptPath), $username, $password);
|
||||
$return = shell_exec($cmd);
|
||||
if (strpos(strtolower($return), 'ok') === false) {
|
||||
throw new \Exception('Plugin helper failed to create user: ' . $user['name']);
|
||||
|
@ -306,7 +311,7 @@ class PluginInstaller
|
|||
$destination = $this->rootPath . '/' . ltrim($destination, '/');
|
||||
}
|
||||
$destination = escapeshellarg($destination);
|
||||
$cmd = sprintf('sudo /etc/raspap/plugins/plugin_helper.sh config %s %s', $source, $destination);
|
||||
$cmd = sprintf('sudo %s config %s %s', escapeshellarg($this->helperScriptPath), $source, $destination);
|
||||
$return = shell_exec($cmd);
|
||||
if (strpos(strtolower($return), 'ok') === false) {
|
||||
throw new \Exception("Failed to copy configuration file: $source to $destination");
|
||||
|
@ -325,7 +330,7 @@ class PluginInstaller
|
|||
foreach ($javascript as $js) {
|
||||
$source = escapeshellarg($pluginDir . DIRECTORY_SEPARATOR . $js);
|
||||
$destination = escapeshellarg($this->rootPath . DIRECTORY_SEPARATOR . 'app/js/plugins/');
|
||||
$cmd = sprintf('sudo /etc/raspap/plugins/plugin_helper.sh javascript %s %s', $source, $destination);
|
||||
$cmd = sprintf('sudo %s javascript %s %s', escapeshellarg($this->helperScriptPath), $source, $destination);
|
||||
$return = shell_exec($cmd);
|
||||
if (strpos(strtolower($return), 'ok') === false) {
|
||||
throw new \Exception("Failed to copy JavaScript file: $source");
|
||||
|
@ -343,13 +348,43 @@ class PluginInstaller
|
|||
{
|
||||
$source = escapeshellarg($source);
|
||||
$destination = escapeshellarg($destination . DIRECTORY_SEPARATOR .$this->pluginPath . DIRECTORY_SEPARATOR . $this->pluginName);
|
||||
$cmd = sprintf('sudo /etc/raspap/plugins/plugin_helper.sh plugin %s %s', $source, $destination);
|
||||
$cmd = sprintf('sudo %s plugin %s %s', escapeshellarg($this->helperScriptPath), $source, $destination);
|
||||
$return = shell_exec($cmd);
|
||||
if (strpos(strtolower($return), 'ok') === false) {
|
||||
throw new \Exception('Failed to copy plugin files to: ' . $destination);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs repository keys for third-party apt packages
|
||||
*
|
||||
* @param array $keys Array containing key_url, keyring, repo, and sources
|
||||
* @throws Exception on key installation failure
|
||||
*/
|
||||
public function installRepositoryKeys(array $keys): void
|
||||
{
|
||||
if (!is_array($keys)) {
|
||||
throw new \Exception("Invalid repository key structure: array expected");
|
||||
}
|
||||
foreach ($keys as $keyData) {
|
||||
if (!isset($keyData['key_url'], $keyData['keyring'], $keyData['repo'], $keyData['sources'])) {
|
||||
throw new \Exception("Invalid repository key structure: " . json_encode($keyData));
|
||||
}
|
||||
$cmd = sprintf(
|
||||
'sudo %s keys %s %s %s %s',
|
||||
escapeshellarg($this->helperScriptPath),
|
||||
escapeshellarg($keyData['key_url']),
|
||||
escapeshellarg($keyData['keyring']),
|
||||
escapeshellarg($keyData['repo']),
|
||||
escapeshellarg($keyData['sources'])
|
||||
);
|
||||
$return = shell_exec($cmd);
|
||||
if (strpos(strtolower($return), 'ok') === false) {
|
||||
throw new \Exception("Failed to add repository and key");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses and returns a downloaded plugin manifest
|
||||
*
|
||||
|
|
|
@ -95,48 +95,50 @@ class Sysinfo
|
|||
|
||||
/*
|
||||
* Returns RPi Model and PCB Revision from Pi Revision Code (cpuinfo)
|
||||
* @see http://www.raspberrypi-spy.co.uk/2012/09/checking-your-raspberry-pi-board-version/
|
||||
* @see https://github.com/raspberrypi/documentation/blob/develop/documentation/asciidoc/computers/raspberry-pi/revision-codes.adoc
|
||||
*/
|
||||
public function rpiRevision()
|
||||
{
|
||||
$revisions = array(
|
||||
'0002' => 'Model B Revision 1.0',
|
||||
'0003' => 'Model B Revision 1.0 + ECN0001',
|
||||
'0004' => 'Model B Revision 2.0 (256 MB)',
|
||||
'0005' => 'Model B Revision 2.0 (256 MB)',
|
||||
'0006' => 'Model B Revision 2.0 (256 MB)',
|
||||
'0007' => 'Model A',
|
||||
'0008' => 'Model A',
|
||||
'0009' => 'Model A',
|
||||
'000d' => 'Model B Revision 2.0 (512 MB)',
|
||||
'000e' => 'Model B Revision 2.0 (512 MB)',
|
||||
'000f' => 'Model B Revision 2.0 (512 MB)',
|
||||
'0010' => 'Model B+',
|
||||
'0013' => 'Model B+',
|
||||
'0011' => 'Compute Module',
|
||||
'0012' => 'Model A+',
|
||||
'a01041' => 'a01041',
|
||||
'a21041' => 'a21041',
|
||||
'900092' => 'PiZero 1.2',
|
||||
'900093' => 'PiZero 1.3',
|
||||
'9000c1' => 'PiZero W',
|
||||
'a02082' => 'Pi 3 Model B',
|
||||
'a22082' => 'Pi 3 Model B',
|
||||
'a32082' => 'Pi 3 Model B',
|
||||
'a52082' => 'Pi 3 Model B',
|
||||
'a020d3' => 'Pi 3 Model B+',
|
||||
'a220a0' => 'Compute Module 3',
|
||||
'a020a0' => 'Compute Module 3',
|
||||
'0002' => 'Raspberry Pi Model B Rev 1.0',
|
||||
'0003' => 'Raspberry Pi Model B Rev 1.0',
|
||||
'0004' => 'Raspberry Pi Model B Rev 2.0',
|
||||
'0005' => 'Raspberry Pi Model B Rev 2.0',
|
||||
'0006' => 'Raspberry Pi Model B Rev 2.0',
|
||||
'0007' => 'Raspberry Pi Model A',
|
||||
'0008' => 'Raspberry Pi Model A',
|
||||
'0009' => 'Raspberry Pi Model A',
|
||||
'000d' => 'Raspberry Pi Model B Rev 2.0',
|
||||
'000e' => 'Raspberry Pi Model B Rev 2.0',
|
||||
'000f' => 'Raspberry Pi Model B Rev 2.0',
|
||||
'0010' => 'Raspberry Pi Model B+',
|
||||
'0013' => 'Raspberry Pi Model B+',
|
||||
'0011' => 'Compute Module 1',
|
||||
'0012' => 'Raspberry Pi Model A+',
|
||||
'a01041' => 'Raspberry Pi 2 Model B',
|
||||
'a21041' => 'Raspberry Pi 2 Model B',
|
||||
'900092' => 'Raspberry Pi Zero 1.2',
|
||||
'900093' => 'Raspberry Pi Zero 1.3',
|
||||
'9000c1' => 'Raspberry Pi Zero W',
|
||||
'a02082' => 'Raspberry Pi 3 Model B',
|
||||
'a22082' => 'Raspberry Pi 3 Model B',
|
||||
'a32082' => 'Raspberry Pi 3 Model B',
|
||||
'a52082' => 'Raspberry Pi 3 Model B+',
|
||||
'9020e0' => 'Raspberry Pi 3 Model A+',
|
||||
'a02100' => 'Compute Module 3+',
|
||||
'a03111' => 'Model 4B Revision 1.1 (1 GB)',
|
||||
'b03111' => 'Model 4B Revision 1.1 (2 GB)',
|
||||
'c03111' => 'Model 4B Revision 1.1 (4 GB)',
|
||||
'a03111' => 'Raspberry Pi 4 Model B (1 GB)',
|
||||
'b03111' => 'Raspberry Pi 4 Model B (2 GB)',
|
||||
'c03111' => 'Raspberry Pi 4 Model B (4 GB)',
|
||||
'b03112' => 'Raspberry Pi 4 Model B (2 GB)',
|
||||
'c03112' => 'Raspberry Pi 4 Model B (4 GB)',
|
||||
'd03114' => 'Raspberry Pi 4 Model B (8 GB)',
|
||||
'902120' => 'Raspberry Pi Zero 2 W',
|
||||
'a03140' => 'Compute Module 4 (1 GB)',
|
||||
'b03140' => 'Compute Module 4 (2 GB)',
|
||||
'c03140' => 'Compute Module 4 (4 GB)',
|
||||
'd03140' => 'Compute Module 4 (8 GB)',
|
||||
'c04170' => 'Pi 5 (4 GB)',
|
||||
'd04170' => 'Pi 5 (8 GB)'
|
||||
'c04170' => 'Raspberry Pi 5 (4 GB)',
|
||||
'd04170' => 'Raspberry Pi 5 (8 GB)'
|
||||
);
|
||||
|
||||
$cpuinfo_array = '';
|
||||
|
@ -155,5 +157,48 @@ class Sysinfo
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if ad blocking is enabled and active
|
||||
*
|
||||
* @return bool $status
|
||||
*/
|
||||
public function adBlockStatus(): bool
|
||||
{
|
||||
exec('cat '. RASPI_ADBLOCK_CONFIG, $return);
|
||||
$arrConf = ParseConfig($return);
|
||||
if (sizeof($arrConf) > 0) {
|
||||
$enabled = true;
|
||||
}
|
||||
exec('pidof dnsmasq | wc -l', $dnsmasq);
|
||||
$dnsmasq_state = ($dnsmasq[0] > 0);
|
||||
$status = $dnsmasq_state && $enabled ? true : false;
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a VPN interface is active
|
||||
*
|
||||
* @return string $interface
|
||||
*/
|
||||
public function getActiveVpnInterface(): ?string
|
||||
{
|
||||
$output = shell_exec('ip a 2>/dev/null');
|
||||
if (!$output) {
|
||||
return null;
|
||||
}
|
||||
$vpnInterfaces = ['wg0', 'tun0', 'tailscale0'];
|
||||
|
||||
// interface must have an 'UP' status and an IP address
|
||||
foreach ($vpnInterfaces as $interface) {
|
||||
if (strpos($output, "$interface:") !== false) {
|
||||
if (preg_match("/\d+: $interface: .*<.*UP.*>/", $output) &&
|
||||
preg_match("/inet\b.*$interface/", $output)) {
|
||||
return $interface;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
136
src/RaspAP/Tokens/CSRFTokenizer.php
Normal file
136
src/RaspAP/Tokens/CSRFTokenizer.php
Normal file
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* CSRF tokenizer class
|
||||
*
|
||||
* @description CSRF tokenizer class for RaspAP
|
||||
* @author Bill Zimmerman <billzimmerman@gmail.com>
|
||||
* @author Martin Glaß <mail@glasz.org>
|
||||
* @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace RaspAP\Tokens;
|
||||
|
||||
class CSRFTokenizer {
|
||||
|
||||
// Constructor
|
||||
public function __construct()
|
||||
{
|
||||
$this->ensureSession();
|
||||
|
||||
// ensure a CSRF token exists in the session
|
||||
if (empty($_SESSION['csrf_token'])) {
|
||||
$this->ensureCSRFSessionToken();
|
||||
header("Location: " .$_SERVER['REQUEST_URI']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($this->csrfValidateRequest()) {
|
||||
$token = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
|
||||
if (!$this->CSRFValidate($token)) {
|
||||
$this->handleInvalidCSRFToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a CSRF token in the session
|
||||
*/
|
||||
public function ensureCSRFSessionToken(): void
|
||||
{
|
||||
if (empty($_SESSION['csrf_token'])) {
|
||||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a CSRF Token to form
|
||||
*/
|
||||
public function CSRFTokenFieldTag(): string
|
||||
{
|
||||
$token = htmlspecialchars($_SESSION['csrf_token']);
|
||||
return '<input type="hidden" name="csrf_token" value="' . $token . '">';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a CSRF meta tag (for use with xhr, for example)
|
||||
*/
|
||||
public function CSRFMetaTag(): string
|
||||
{
|
||||
// if session has expired or user has logged out,
|
||||
// create a new session and token
|
||||
if (empty($_SESSION['csrf_token'])) {
|
||||
$this->ensureSession();
|
||||
$this->ensureCSRFSessionToken();
|
||||
return $_SESSION['csrf_token'];
|
||||
} else {
|
||||
$token = htmlspecialchars($_SESSION['csrf_token']);
|
||||
return '<meta name="csrf_token" content="' . $token . '">';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a CSRF Token
|
||||
*
|
||||
* @param string $token
|
||||
*/
|
||||
public function CSRFValidate(string $token): bool
|
||||
{
|
||||
if (empty($_SESSION['csrf_token']) || !is_string($_SESSION['csrf_token'])) {
|
||||
error_log('Session expired or CSRF token is missing.');
|
||||
header('Location: /login');
|
||||
exit;
|
||||
}
|
||||
|
||||
$post_token = $token ?? null;
|
||||
$header_token = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null;
|
||||
|
||||
if (empty($post_token) && is_null($header_token)) {
|
||||
error_log('CSRF token missing in the request');
|
||||
return false;
|
||||
}
|
||||
$request_token = $post_token ?: $header_token;
|
||||
|
||||
if (hash_equals($_SESSION['csrf_token'], $request_token)) {
|
||||
return true;
|
||||
} else {
|
||||
error_log('CSRF token mismatch');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should the request be CSRF-validated?
|
||||
*/
|
||||
public function csrfValidateRequest(): bool
|
||||
{
|
||||
$request_method = strtolower($_SERVER['REQUEST_METHOD']);
|
||||
return in_array($request_method, [ "post", "put", "patch", "delete" ]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle invalid CSRF
|
||||
*/
|
||||
public function handleInvalidCSRFToken(): string
|
||||
{
|
||||
if (function_exists('http_response_code')) {
|
||||
http_response_code(500);
|
||||
echo 'Invalid CSRF token';
|
||||
} else {
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
header('Content-Type: text/plain');
|
||||
echo 'Invalid CSRF token';
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
protected function ensureSession()
|
||||
{
|
||||
if (session_status() == PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
368
src/RaspAP/UI/Dashboard.php
Normal file
368
src/RaspAP/UI/Dashboard.php
Normal file
|
@ -0,0 +1,368 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Dashboard UI class
|
||||
*
|
||||
* @description A class for rendering the RaspAP dashboard
|
||||
* @author Bill Zimmerman <billzimmerman@gmail.com>
|
||||
* @license https://github.com/raspap/raspap-webgui/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace RaspAP\UI;
|
||||
|
||||
class Dashboard {
|
||||
|
||||
private string $firewallConfig;
|
||||
|
||||
public function __construct() {
|
||||
$this->firewallConfig = RASPI_CONFIG.'/networking/firewall.conf';
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the management page for an associated VPN
|
||||
*
|
||||
* @param string $interface
|
||||
* @return string
|
||||
*/
|
||||
public function getVpnManaged(?string $interface = null): ?string
|
||||
{
|
||||
switch ($interface) {
|
||||
case 'wg0':
|
||||
return '/wg_conf';
|
||||
case 'tun0':
|
||||
return '/openvpn_conf';
|
||||
case 'tailscale0':
|
||||
return '/plugin__Tailscale';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses output of iw, extracts frequency (MHz) and classifies
|
||||
* it as 2.4 or 5 GHz. Returns null if not found
|
||||
*
|
||||
* @param string $interface
|
||||
* @return string frequency
|
||||
*/
|
||||
public function getFrequencyBand(string $interface): ?string
|
||||
{
|
||||
$output = shell_exec("iw dev " . escapeshellarg($interface) . " info 2>/dev/null");
|
||||
if (!$output) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (preg_match('/channel\s+\d+\s+\((\d+)\s+MHz\)/', $output, $matches)) {
|
||||
$frequency = (int)$matches[1];
|
||||
|
||||
if ($frequency >= 2400 && $frequency < 2500) {
|
||||
return "2.4";
|
||||
} elseif ($frequency >= 5000 && $frequency < 6000) {
|
||||
return "5";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Aggregate function that fetches output of ip and calls
|
||||
* functions to parse output into discreet network properties
|
||||
*
|
||||
* @param string $interface
|
||||
* @return array
|
||||
*/
|
||||
public function getInterfaceDetails(string $interface): array
|
||||
{
|
||||
$output = shell_exec('ip a show ' . escapeshellarg($interface));
|
||||
if (!$output) {
|
||||
return [
|
||||
'mac' => _('No MAC Address Found'),
|
||||
'ipv4' => 'None',
|
||||
'ipv4_netmask' => '-',
|
||||
'ipv6' => _('No IPv6 Address Found'),
|
||||
'state' => 'unknown'
|
||||
];
|
||||
}
|
||||
$cleanOutput = preg_replace('/\s\s+/', ' ', implode(' ', explode("\n", $output)));
|
||||
|
||||
return [
|
||||
'mac' => $this->getMacAddress($cleanOutput),
|
||||
'ipv4' => $this->getIPv4Addresses($cleanOutput),
|
||||
'ipv4_netmask' => $this->getIPv4Netmasks($cleanOutput),
|
||||
'ipv6' => $this->getIPv6Addresses($cleanOutput),
|
||||
'state' => $this->getInterfaceState($cleanOutput),
|
||||
];
|
||||
}
|
||||
|
||||
private function getMacAddress(string $output): string
|
||||
{
|
||||
return preg_match('/link\/ether ([0-9a-f:]+)/i', $output, $matches) ? $matches[1] : _('No MAC Address Found');
|
||||
}
|
||||
|
||||
private function getIPv4Addresses(string $output): string
|
||||
{
|
||||
if (!preg_match_all('/inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/([0-3][0-9])/i', $output, $matches, PREG_SET_ORDER)) {
|
||||
return 'None';
|
||||
}
|
||||
|
||||
$addresses = array_column($matches, 1);
|
||||
return implode(' ', $addresses);
|
||||
}
|
||||
|
||||
private function getIPv4Netmasks(string $output): string
|
||||
{
|
||||
if (!preg_match_all('/inet (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/([0-3][0-9])/i', $output, $matches, PREG_SET_ORDER)) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$netmasks = array_map(fn($match) => long2ip(-1 << (32 - (int)$match[2])), $matches);
|
||||
return implode(' ', $netmasks);
|
||||
}
|
||||
|
||||
private function getIPv6Addresses(string $output): string
|
||||
{
|
||||
return preg_match_all('/inet6 ([a-f0-9:]+)/i', $output, $matches) && isset($matches[1])
|
||||
? implode(' ', $matches[1])
|
||||
: _('No IPv6 Address Found');
|
||||
}
|
||||
|
||||
private function getInterfaceState(string $output): string
|
||||
{
|
||||
return preg_match('/state (UP|DOWN)/i', $output, $matches) ? $matches[1] : 'unknown';
|
||||
}
|
||||
|
||||
public function getWirelessDetails(string $interface): array
|
||||
{
|
||||
$output = shell_exec('iw dev ' . escapeshellarg($interface) . ' info');
|
||||
if (!$output) {
|
||||
return ['bssid' => '-', 'ssid' => '-'];
|
||||
}
|
||||
$cleanOutput = preg_replace('/\s\s+/', ' ', trim($output)); // Fix here
|
||||
|
||||
return [
|
||||
'bssid' => $this->getConnectedBSSID($cleanOutput),
|
||||
'ssid' => $this->getSSID($cleanOutput),
|
||||
];
|
||||
}
|
||||
|
||||
private function getConnectedBSSID(string $output): string
|
||||
{
|
||||
return preg_match('/Connected to (([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2}))/i', $output, $matches)
|
||||
? $matches[1]
|
||||
: '-';
|
||||
}
|
||||
|
||||
private function getSSID(string $output): string
|
||||
{
|
||||
return preg_match('/ssid ([^\n\s]+)/i', $output, $matches)
|
||||
? $matches[1]
|
||||
: '-';
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses the output of iw to obtain a list of wireless clients
|
||||
*
|
||||
* @return integer $clientCount
|
||||
*/
|
||||
public function getWirelessClients()
|
||||
{
|
||||
exec('iw dev wlan0 station dump', $output, $status);
|
||||
|
||||
if ($status !== 0) {
|
||||
return 0;
|
||||
}
|
||||
// enumerate 'station' entries (each represents a wireless client)
|
||||
$clientCount = 0;
|
||||
foreach ($output as $line) {
|
||||
if (strpos($line, 'Station') === 0) {
|
||||
$clientCount++;
|
||||
}
|
||||
}
|
||||
return $clientCount;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieves ethernet neighbors from ARP cache, parses DHCP leases
|
||||
* to find matching MAC addresses and returns only clients that
|
||||
* exist in both sources
|
||||
*
|
||||
* @return int $ethernetClients
|
||||
*/
|
||||
public function getEthernetClients(): int
|
||||
{
|
||||
$ethernetClients = [];
|
||||
|
||||
// Get ARP table entries and filter ethernet clients
|
||||
$arpOutput = shell_exec("ip neigh show");
|
||||
if ($arpOutput) {
|
||||
foreach (explode("\n", trim($arpOutput)) as $line) {
|
||||
/* match both traditional interface names (eth0...n) and predictable names like
|
||||
* enp3s0 (PCI ethernet)
|
||||
* eno1 (onboard ethernet)
|
||||
* ens160, etc.
|
||||
* ...ignoring STALE entries
|
||||
*/
|
||||
if (preg_match('/^(\S+) dev (eth[0-9]+|en\w+) lladdr (\S+) (REACHABLE|DELAY|PROBE)/', $line, $matches)) {
|
||||
$ethernetClients[$matches[3]] = $matches[1]; // MAC => IP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compare against active DHCP leases
|
||||
$leaseFile = RASPI_DNSMASQ_LEASES;
|
||||
if (file_exists($leaseFile)) {
|
||||
$leases = file($leaseFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||
$activeLeases = [];
|
||||
foreach ($leases as $lease) {
|
||||
$fields = preg_split('/\s+/', $lease);
|
||||
if (count($fields) >= 3) {
|
||||
$activeLeases[$fields[1]] = true; // MAC as key
|
||||
}
|
||||
}
|
||||
// keep only clients that exist in the DHCP lease file
|
||||
$ethernetClients = array_intersect_key($ethernetClients, $activeLeases);
|
||||
}
|
||||
return count($ethernetClients);
|
||||
}
|
||||
|
||||
public function formatClientLabel($clientCount)
|
||||
{
|
||||
return ngettext('client', 'clients', $clientCount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines the device's primary connection type by
|
||||
* parsing the output of ip route; the interface listed
|
||||
* as the default gateway is used for internet connectivity.
|
||||
*
|
||||
* The following interface classifications are matched:
|
||||
* - ethernet (eth0, enp*, ens*, enx*)
|
||||
* - wireless (wlan*, wlp*, wlx*)
|
||||
* - tethered USB (usb*, eth1-9)
|
||||
* - cellular (ppp*, wwan*, wwp*)
|
||||
* - fallback
|
||||
* @return string
|
||||
*/
|
||||
public function getConnectionType(): string
|
||||
{
|
||||
// get the interface associated with the default route
|
||||
$interface = trim(shell_exec("ip route show default | awk '{print $5}'"));
|
||||
|
||||
if (empty($interface)) {
|
||||
return 'unknown';
|
||||
}
|
||||
// classify interface type
|
||||
if (preg_match('/^eth0|enp\d+s\d+|ens\d+s\d+|enx[0-9a-f]*/', $interface)) {
|
||||
return 'ethernet';
|
||||
}
|
||||
if (preg_match('/^wlan\d+|wlp\d+s\d+|wlx[0-9a-f]*/', $interface)) {
|
||||
return 'wireless';
|
||||
}
|
||||
if (preg_match('/^usb\d+|^eth[1-9]\d*/', $interface)) {
|
||||
return 'tethering';
|
||||
}
|
||||
if (preg_match('/^ppp\d+|wwan\d+|wwp\d+s\d+/', $interface)) {
|
||||
return 'cellular';
|
||||
}
|
||||
|
||||
// if none match, return the interface name as a fallback
|
||||
return "other ($interface)";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fontawesome icon associated with a connection
|
||||
* type/class
|
||||
*
|
||||
* @param $type
|
||||
* @return string
|
||||
*/
|
||||
public function getConnectionIcon($type): string
|
||||
{
|
||||
switch (strtolower($type)) {
|
||||
case 'ethernet':
|
||||
return 'fa-ethernet';
|
||||
case 'wireless':
|
||||
return 'fa-wifi';
|
||||
case 'tethering':
|
||||
return 'fa-mobile-alt';
|
||||
case 'cellular':
|
||||
return 'fa-broadcast-tower';
|
||||
default:
|
||||
return 'fa-question-circle'; // unknown
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the firewall's current status
|
||||
*
|
||||
* @return bool status
|
||||
*/
|
||||
public function firewallEnabled(): bool
|
||||
{
|
||||
$conf = array();
|
||||
if (file_exists($this->firewallConfig) ) {
|
||||
$conf = parse_ini_file($this->firewallConfig);
|
||||
}
|
||||
if ($conf["firewall-enable"] == 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an SVG resource associated with a Pi revision
|
||||
*
|
||||
* @param string $deviceName
|
||||
* @return string
|
||||
*/
|
||||
public function getDeviceImage($deviceName): string
|
||||
{
|
||||
if (stripos($deviceName, 'zero') !== false) {
|
||||
return 'zero.php';
|
||||
}
|
||||
if (stripos($deviceName, 'compute') !== false) {
|
||||
return 'compute.php';
|
||||
}
|
||||
return 'default.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles dashboard page actions
|
||||
*
|
||||
* @param string $state
|
||||
* @param array $post
|
||||
* @param object $status
|
||||
* @param string $interface
|
||||
*/
|
||||
public function handlePageAction(string $state, array $post, $status, string $interface): object
|
||||
{
|
||||
if (!RASPI_MONITOR_ENABLED) {
|
||||
if (isset($post['ifdown_wlan0'])) {
|
||||
if ($state === 'up') {
|
||||
$status->addMessage(sprintf(_('Interface %s is going %s'), $interface, _('down')), 'warning');
|
||||
exec('sudo ip link set ' .escapeshellarg($interface). ' down');
|
||||
$status->addMessage(sprintf(_('Interface %s is %s'), $interface, _('down')), 'success');
|
||||
} elseif ($details['state'] === 'unknown') {
|
||||
$status->addMessage(_('Interface state unknown'), 'danger');
|
||||
} else {
|
||||
$status->addMessage(sprintf(_('Interface %s is already %s'), $interface, _('down')), 'warning');
|
||||
}
|
||||
} elseif (isset($post['ifup_wlan0'])) {
|
||||
if ($state === 'down') {
|
||||
$status->addMessage(sprintf(_('Interface %s is going %s'), $interface, _('up')), 'warning');
|
||||
exec('sudo ip link set ' .escapeshellarg($interface). ' up');
|
||||
exec('sudo ip -s a f label ' .escapeshellarg($interface));
|
||||
usleep(250000);
|
||||
$status->addMessage(sprintf(_('Interface %s is %s'), $interface, _('up')), 'success');
|
||||
} elseif ($state === 'unknown') {
|
||||
$status->addMessage(_('Interface state unknown'), 'danger');
|
||||
} else {
|
||||
$status->addMessage(sprintf(_('Interface %s is already %s'), $interface, _('up')), 'warning');
|
||||
}
|
||||
}
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ class Sidebar {
|
|||
public function __construct() {
|
||||
// Load default sidebar items
|
||||
$this->addItem(_('Dashboard'), 'fa-solid fa-gauge-high', 'wlan0_info', 10);
|
||||
$this->addItem(_('Hotspot'), 'far fa-dot-circle', 'hostapd_conf', 20,
|
||||
$this->addItem(_('Hotspot'), 'fas fa-bullseye', 'hostapd_conf', 20,
|
||||
fn() => RASPI_HOTSPOT_ENABLED
|
||||
);
|
||||
$this->addItem(_('DHCP Server'), 'fas fa-exchange-alt', 'dhcpd_conf', 30,
|
||||
|
@ -39,9 +39,6 @@ class Sidebar {
|
|||
);
|
||||
$this->addItem(_(getProviderValue($_SESSION["providerID"], "name")), 'fas fa-shield-alt', 'provider_conf', 90,
|
||||
fn() => RASPI_VPN_PROVIDER_ENABLED
|
||||
);
|
||||
$this->addItem(_('Authentication'), 'fas fa-user-lock', 'auth_conf', 100,
|
||||
fn() => RASPI_CONFAUTH_ENABLED
|
||||
);
|
||||
$this->addItem(_('Data usage'), 'fas fa-chart-area', 'data_use', 110,
|
||||
fn() => RASPI_VNSTAT_ENABLED
|
||||
|
|
|
@ -69,7 +69,7 @@ require_once 'app/lib/Parsedown.php';
|
|||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="col-md-12 mb-3 mt-1" id="msg-check-update"><?php echo _("Application is being updated..."); ?></div>
|
||||
<div class="ms-5"><i class="fas fa-check me-2 invisible" id="updateStep1"></i><?php echo _("Configuring update"); ?></div>
|
||||
<div class="ms-5"><i class="fas fa-check me-2" id="updateStep1"></i><?php echo _("Configuring update"); ?></div>
|
||||
<div class="ms-5"><i class="fas fa-check me-2 invisible" id="updateStep2"></i><?php echo _("Updating sources"); ?></div>
|
||||
<div class="ms-5"><i class="fas fa-check me-2 invisible" id="updateStep3"></i><?php echo _("Installing package updates"); ?></div>
|
||||
<div class="ms-5"><i class="fas fa-check me-2 invisible" id="updateStep4"></i><?php echo _("Downloading latest files"); ?></div>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<div class="card-body">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form role="form" action="adblock_conf" enctype="multipart/form-data" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField();?>
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item"><a class="nav-link active" id="blocklisttab" href="#adblocklistsettings" data-bs-toggle="tab"><?php echo _("Blocklist settings"); ?></a></li>
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
<?php ob_start() ?>
|
||||
<?php if (!RASPI_MONITOR_ENABLED) : ?>
|
||||
<input type="submit" class="btn btn-outline btn-primary" name="UpdateAdminPassword" value="<?php echo _("Save settings"); ?>" />
|
||||
<input type="submit" class="btn btn-warning" name="logout" value="<?php echo _("Logout") ?>" onclick="disableValidation(this.form)"/>
|
||||
<?php endif ?>
|
||||
<?php $buttons = ob_get_clean(); ob_end_clean() ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<i class="fas fa-user-lock me-2"></i><?php echo _("Authentication"); ?>
|
||||
<div class="col">
|
||||
<i class="fas fa-user-lock me-2"></i><?php echo _("Authentication"); ?>
|
||||
</div>
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.card-header -->
|
||||
|
@ -12,7 +19,7 @@
|
|||
<?php $status->showMessages(); ?>
|
||||
<h4><?php echo _("Authentication settings") ;?></h4>
|
||||
<form role="form" action="auth_conf" method="POST" class="needs-validation" novalidate>
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<div class="row">
|
||||
<div class="mb-3 col-md-6">
|
||||
<label for="username"><?php echo _("Username"); ?></label>
|
||||
|
@ -58,7 +65,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input type="submit" class="btn btn-outline btn-primary" name="UpdateAdminPassword" value="<?php echo _("Save settings"); ?>" />
|
||||
<?php echo $buttons ?>
|
||||
</form>
|
||||
</div><!-- /.card-body -->
|
||||
<div class="card-footer"></div>
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<div class="row" id="wpaConf">
|
||||
<div class="col">
|
||||
<form method="POST" action="wpa_conf" name="wpa_conf_form">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<input type="hidden" name="client_settings" ?>
|
||||
<div class="js-wifi-stations loading-spinner"></div>
|
||||
</form>
|
||||
|
|
|
@ -1,149 +1,56 @@
|
|||
<?php ob_start() ?>
|
||||
<?php if (!RASPI_MONITOR_ENABLED) : ?>
|
||||
<?php if ($state === "down") : ?>
|
||||
<input type="submit" class="btn btn-success mt-2" value="<?php echo _("Start").' '.$interface ?>" name="ifup_wlan0" />
|
||||
<?php else : ?>
|
||||
<input type="submit" class="btn btn-warning mt-2" value="<?php echo _("Stop").' '.$interface ?>" name="ifdown_wlan0" />
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
<button type="button" onClick="window.location.reload();" class="btn btn-outline btn-primary mt-2"><i class="fas fa-sync-alt"></i> <?php echo _("Refresh") ?></a>
|
||||
<?php $buttons = ob_get_clean(); ob_end_clean() ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<i class="fas fa-tachometer-alt fa-fw me-2"></i><?php echo _("Dashboard"); ?>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn btn-light btn-icon-split btn-sm service-status float-end">
|
||||
<span class="icon"><i class="fas fa-circle service-status-<?php echo $ifaceStatus ?>"></i></span>
|
||||
<span class="text service-status"><?php echo strtolower($apInterface) .' '. _($ifaceStatus) ?></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="col">
|
||||
<i class="fas fa-tachometer-alt fa-fw me-2"></i>
|
||||
<?php echo _("Dashboard"); ?>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn btn-light btn-icon-split btn-sm service-status float-end">
|
||||
<span class="icon"><i class="fas fa-circle service-status-<?php echo $state ?>"></i></span>
|
||||
<span class="text service-status"><?php echo strtolower($interface) .' '. _($state) ?></span>
|
||||
</button>
|
||||
</div>
|
||||
</div><!-- /.row -->
|
||||
</div><!-- /.card-header -->
|
||||
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form action="wlan0_info" method="POST">
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title"><?php echo _("Hourly traffic amount"); ?></h4>
|
||||
<div id="divInterface" class="d-none"><?php echo $apInterface; ?></div>
|
||||
<div class="col-md-12">
|
||||
<div class="col dbChart">
|
||||
<canvas id="divDBChartBandwidthhourly"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.card-body -->
|
||||
</div><!-- /.card-->
|
||||
</div>
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item"><a class="nav-link active" id="statustab" href="#status" aria-controls="status" data-bs-toggle="tab"><?php echo _("Status"); ?></a></li>
|
||||
<li class="nav-item"><a class="nav-link" id="datatab" href="#data" data-bs-toggle="tab"><?php echo _("Data usage"); ?></a></li>
|
||||
</ul>
|
||||
|
||||
<div class="col-sm-6 align-items-stretch">
|
||||
<div class="card h-100">
|
||||
<div class="card-body wireless">
|
||||
<h4 class="card-title"><?php echo _("Wireless Client"); ?></h4>
|
||||
<div class="row ms-1">
|
||||
<div class="col-sm">
|
||||
<div class="row mb-1">
|
||||
<div class="info-item col"><?php echo _("Connected To"); ?></div><div class="info-value col"><?php echo htmlspecialchars($connectedSSID, ENT_QUOTES); ?></div>
|
||||
</div>
|
||||
<div class="row mb-1">
|
||||
<div class="info-item col"><?php echo _("Interface"); ?></div><div class="info-value col"><?php echo htmlspecialchars($clientInterface); ?></div>
|
||||
</div>
|
||||
<div class="row mb-1">
|
||||
<div class="info-item col"><?php echo _("AP Mac Address"); ?></div><div class="info-value col"><?php echo htmlspecialchars($connectedBSSID, ENT_QUOTES); ?></div>
|
||||
</div>
|
||||
<div class="row mb-1">
|
||||
<div class="info-item col"><?php echo _("Bitrate"); ?></div><div class="info-value col"><?php echo htmlspecialchars($bitrate, ENT_QUOTES); ?></div>
|
||||
</div>
|
||||
<div class="row mb-1">
|
||||
<div class="info-item col"><?php echo _("Signal Level"); ?></div><div class="info-value col"><?php echo htmlspecialchars($signalLevel, ENT_QUOTES); ?></div>
|
||||
</div>
|
||||
<div class="row mb-1">
|
||||
<div class="info-item col"><?php echo _("Transmit Power"); ?></div><div class="info-value col"><?php echo htmlspecialchars($txPower, ENT_QUOTES); ?></div>
|
||||
</div>
|
||||
<div class="row mb-1">
|
||||
<div class="info-item col"><?php echo _("Frequency"); ?></div><div class="info-value col"><?php echo htmlspecialchars($frequency, ENT_QUOTES); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md d-flex">
|
||||
<script>var linkQ = <?php echo json_encode($strLinkQuality); ?>;</script>
|
||||
<div class="chart-container">
|
||||
<canvas id="divChartLinkQ"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div><!--row-->
|
||||
</div><!-- /.card-body -->
|
||||
</div><!-- /.card -->
|
||||
</div><!-- /.col-md-6 -->
|
||||
<div class="col-sm-6">
|
||||
<div class="card h-100 mb-3">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title"><?php echo _("Connected Devices"); ?></h4>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<?php if ($bridgedEnable == 1) : ?>
|
||||
<th><?php echo _("MAC Address"); ?></th>
|
||||
<?php else : ?>
|
||||
<th><?php echo _("Host name"); ?></th>
|
||||
<th><?php echo _("IP Address"); ?></th>
|
||||
<th><?php echo _("MAC Address"); ?></th>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($bridgedEnable == 1) : ?>
|
||||
<tr>
|
||||
<td><small class="text-muted"><?php echo _("Bridged AP mode is enabled. For Hostname and IP, see your router's admin page.");?></small></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php foreach (array_slice($clients,0, 2) as $client) : ?>
|
||||
<tr>
|
||||
<?php if ($arrHostapdConf['BridgedEnable'] == 1): ?>
|
||||
<td><?php echo htmlspecialchars($client, ENT_QUOTES) ?></td>
|
||||
<?php else : ?>
|
||||
<?php $props = explode(' ', $client) ?>
|
||||
<td><?php echo htmlspecialchars($props[3], ENT_QUOTES) ?></td>
|
||||
<td><?php echo htmlspecialchars($props[2], ENT_QUOTES) ?></td>
|
||||
<td><?php echo htmlspecialchars($props[1], ENT_QUOTES) ?></td>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if (sizeof($clients) >2) : ?>
|
||||
<div class="col-lg-12 float-end">
|
||||
<a class="btn btn-outline-info" role="button" href="<?php echo $moreLink ?>"><?php echo _("More");?> <i class="fas fa-chevron-right"></i></a>
|
||||
</div>
|
||||
<?php elseif (sizeof($clients) ==0) : ?>
|
||||
<div class="col-lg-12 mt-3"><?php echo _("No connected devices");?></div>
|
||||
<?php endif; ?>
|
||||
</div><!-- /.table-responsive -->
|
||||
</div><!-- /.card-body -->
|
||||
</div><!-- /.card -->
|
||||
</div><!-- /.col-md-6 -->
|
||||
</div><!-- /.row -->
|
||||
|
||||
<div class="col-lg-12 mt-3">
|
||||
<div class="row">
|
||||
<form action="wlan0_info" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php if (!RASPI_MONITOR_ENABLED) : ?>
|
||||
<?php if (!$wlan0up) : ?>
|
||||
<input type="submit" class="btn btn-success" value="<?php echo _("Start").' '.$apInterface ?>" name="ifup_wlan0" />
|
||||
<?php else : ?>
|
||||
<input type="submit" class="btn btn-warning" value="<?php echo _("Stop").' '.$apInterface ?>" name="ifdown_wlan0" />
|
||||
<?php endif ?>
|
||||
<?php endif ?>
|
||||
<button type="button" onClick="window.location.reload();" class="btn btn-outline btn-primary"><i class="fas fa-sync-alt"></i> <?php echo _("Refresh") ?></a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<?php echo renderTemplate("dashboard/status", $__template_data) ?>
|
||||
<?php echo renderTemplate("dashboard/data", $__template_data) ?>
|
||||
</div><!-- /.tab-content -->
|
||||
|
||||
<?php echo $buttons ?>
|
||||
</form>
|
||||
</div><!-- /.card-body -->
|
||||
<div class="card-footer"><?php echo _("Information provided by ip and iw and from system"); ?></div>
|
||||
|
||||
<div class="card-footer"><?php echo _("Information provided by raspap.sysinfo"); ?></div>
|
||||
|
||||
</div><!-- /.card -->
|
||||
</div><!-- /.col-lg-12 -->
|
||||
</div><!-- /.row -->
|
||||
<script type="text/javascript"<?php //echo ' nonce="'.$csp_page_nonce.'"'; ?>>
|
||||
// js translations:
|
||||
var t = new Array();
|
||||
t['send'] = '<?php echo addslashes(_('Send')); ?>';
|
||||
t['receive'] = '<?php echo addslashes(_('Receive')); ?>';
|
||||
</script>
|
||||
|
||||
|
|
19
templates/dashboard/data.php
Normal file
19
templates/dashboard/data.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<div class="tab-pane" id="data">
|
||||
<h4 class="card-title mt-3">
|
||||
<?php echo _("Hourly traffic"); ?>
|
||||
</h4>
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="col dbChart">
|
||||
<canvas id="divDBChartBandwidthhourly"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div><!-- /.tab-pane | data tab -->
|
||||
|
||||
<script type="text/javascript"<?php //echo ' nonce="'.$csp_page_nonce.'"'; ?>>
|
||||
// js translations:
|
||||
var t = new Array();
|
||||
t['send'] = '<?php echo addslashes(_('Send')); ?>';
|
||||
t['receive'] = '<?php echo addslashes(_('Receive')); ?>';
|
||||
</script>
|
123
templates/dashboard/status.php
Normal file
123
templates/dashboard/status.php
Normal file
|
@ -0,0 +1,123 @@
|
|||
<div class="tab-pane active" id="status">
|
||||
<h4 class="card-title mt-3">
|
||||
<?php echo _("Current status"); ?>
|
||||
</h4>
|
||||
<div class="dashboard-container row">
|
||||
<div class="connections-left col-lg-4">
|
||||
<div class="connection-item">
|
||||
<a href="/network_conf" class="<?php echo $ethernetActive; ?>"><span><?php echo _("Ethernet"); ?></span></a>
|
||||
<a href="/network_conf" class="<?php echo $ethernetActive; ?>"><i class="fas fa-ethernet fa-2xl"></i></a>
|
||||
</div>
|
||||
<div class="connection-item">
|
||||
<a href="/network_conf" class="<?php echo $wirelessActive; ?>"><span><?php echo _("Repeater"); ?></span>
|
||||
<a href="/network_conf" class="<?php echo $wirelessActive; ?>"><i class="fas fa-wifi fa-2xl"></i></a>
|
||||
</div>
|
||||
<div class="connection-item">
|
||||
<a href="/network_conf" class="<?php echo $tetheringActive; ?>"><span><?php echo _("Tethering"); ?></span></a>
|
||||
<a href="/network_conf" class="<?php echo $tetheringActive; ?>"><i class="fas fa-mobile-alt fa-2xl"></i></a>
|
||||
</div>
|
||||
<div class="connection-item">
|
||||
<a href="/network_conf" class="<?php echo $cellularActive; ?>"><span><?php echo _("Cellular"); ?></span></a>
|
||||
<a href="/network_conf" class="<?php echo $cellularActive; ?>"><i class="fas fa-broadcast-tower fa-2xl"></i></a>
|
||||
</div>
|
||||
<img src="app/img/dashed.svg" class="dashed-lines" alt="">
|
||||
<img src="<?php echo htmlspecialchars(renderConnection($connectionType)); ?>" class="solid-lines" alt="Network connection">
|
||||
</div>
|
||||
<div class="center-device col-12 col-lg-4">
|
||||
<div class="center-device-top">
|
||||
<a href="/system_info"><img class="device-illustration" src="app/img/devices/<?php echo $deviceImage; ?>" alt="<?php echo htmlspecialchars($revision, ENT_QUOTES); ?>"></a>
|
||||
<div class="device-label"><a href="/system_info"><?php echo htmlspecialchars($revision, ENT_QUOTES); ?></a></div>
|
||||
<div class="mt-1 small"><?php echo _("IP Address"); ?>: <a href="/dhcpd_conf"><?php echo htmlspecialchars($ipv4Address, ENT_QUOTES); ?></a></div>
|
||||
<div class="small"><?php echo _("Netmask"); ?>: <a href="/dhcpd_conf"><?php echo htmlspecialchars($ipv4Netmask, ENT_QUOTES); ?></a></div>
|
||||
<div class="small"><?php echo _("MAC Address"); ?>: <a href="/dhcpd_conf"><?php echo htmlspecialchars($macAddress, ENT_QUOTES); ?></a></div>
|
||||
<div class="small"><?php echo _("SSID"); ?>: <a href="/hostapd_conf"><?php echo htmlspecialchars($ssid, ENT_QUOTES); ?></a></div>
|
||||
</div>
|
||||
|
||||
<div class="bottom">
|
||||
<div class="device-status">
|
||||
<a href="/hostapd_conf">
|
||||
<div class="status-item <?php echo $hostapdStatus; ?>">
|
||||
<i class="fas fa-bullseye fa-2xl"></i>
|
||||
<span><?php echo _('AP'); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/hostapd_conf?tab=advanced">
|
||||
<div class="status-item <?php echo $bridgedStatus; ?>">
|
||||
<i class="fas fa-bridge fa-2xl"></i>
|
||||
<span><?php echo _('Bridged'); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/adblock_conf">
|
||||
<div class="status-item <?php echo $adblockStatus; ?>">
|
||||
<i class="far fa-hand-paper fa-2xl"></i>
|
||||
<span><?php echo _('Adblock'); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<a href="<?php echo $vpnManaged; ?>">
|
||||
<div class="status-item <?php echo $vpnStatus; ?>">
|
||||
<i class="fas fa-shield-alt fa-2xl"></i>
|
||||
<span><?php echo _('VPN'); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
<?php echo $firewallManaged; ?>
|
||||
<div class="status-item <?php echo $firewallStatus; ?>">
|
||||
<span class="fa-stack fa-2xl" style="line-height: 0!important;height: 100%!important;">
|
||||
<i class="fas fa-fire-flame-curved fa-stack-1x"></i>
|
||||
<?php echo $firewallUnavailable; ?>
|
||||
</span>
|
||||
<span><?php echo _('Firewall'); ?></span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="wifi-bands">
|
||||
<a href="/hostapd_conf"><span class="band <?php echo $freq5active; ?>"><?php echo _("5G"); ?></span></a>
|
||||
<a href="/hostapd_conf"><span class="band <?php echo $freq24active; ?>"><?php echo _("2.4G"); ?></span></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clients-mobile">
|
||||
<div class="client-type">
|
||||
<a href="/network_conf">
|
||||
<i class="fas fa-globe"></i>
|
||||
<div class="client-count">
|
||||
<i class="fas <?php echo $connectionIcon; ?> badge-icon"></i>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="client-type">
|
||||
<a href="/dhcpd_conf">
|
||||
<i class="fas fa-laptop <?php echo $totalClientsActive; ?>"></i>
|
||||
<span class="client-count"><?php echo $totalClients; ?></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="connections-right col-lg-4">
|
||||
<div class="d-flex flex-column justify-content-around h-100">
|
||||
<div class="connection-item connection-right">
|
||||
<a href="/dhcpd_conf" class="<?php echo $wirelessClientActive; ?>">
|
||||
<span class="fa-stack">
|
||||
<i class="fas fa-laptop fa-stack-1x fa-2xl"></i>
|
||||
<i class="fas fa-wifi fa-stack-1x fa-xs"></i>
|
||||
</span>
|
||||
</a>
|
||||
<a href="/dhcpd_conf"><span class="text-nowrap <?php echo $wirelessClientActive; ?>"><?php echo $wirelessClientLabel; ?></span></a>
|
||||
</div>
|
||||
<div class="connection-item connection-right">
|
||||
<a href="/dhcpd_conf" class="<?php echo $ethernetClientActive; ?>">
|
||||
<span class="fa-stack">
|
||||
<i class="fas fa-laptop fa-stack-1x fa-2xl"></i>
|
||||
<i class="fas fa-ethernet fa-stack-1x fa-xs"></i>
|
||||
</span>
|
||||
</a>
|
||||
<a href="/dhcpd_conf"><span class="text-nowrap <?php echo $ethernetClientActive; ?>"><?php echo $ethernetClientLabel; ?></span></a>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo renderClientConnections($wirelessClients, $ethernetClients); ?>
|
||||
<img src="app/img/right-dashed.svg" class="dashed-lines dashed-lines-right" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.tab-pane | status tab -->
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
<div class="card-body">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form method="POST" action="dhcpd_conf" class="js-dhcp-settings-form needs-validation" novalidate>
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs mb-3">
|
||||
|
|
|
@ -20,11 +20,17 @@
|
|||
<tbody>
|
||||
<?php foreach ($leases as $lease) : ?>
|
||||
<tr>
|
||||
<?php foreach (explode(' ', $lease) as $prop) : ?>
|
||||
<td><?php echo htmlspecialchars($prop, ENT_QUOTES) ?></td>
|
||||
<?php endforeach ?>
|
||||
<?php
|
||||
$props = explode(' ', $lease);
|
||||
if (!empty($props)) {
|
||||
$props[0] = date('Y-m-d H:i:s', (int)$props[0]);
|
||||
}
|
||||
?>
|
||||
<?php foreach ($props as $prop) : ?>
|
||||
<td><?php echo htmlspecialchars($prop, ENT_QUOTES) ?></td>
|
||||
<?php endforeach ?>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
<?php endforeach ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div><!-- /.table-responsive -->
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<i class="far fa-dot-circle me-2"></i><?php echo _("Hotspot"); ?>
|
||||
<i class="fas fa-bullseye me-2"></i><?php echo _("Hotspot"); ?>
|
||||
</div>
|
||||
<div class="col">
|
||||
<button class="btn btn-light btn-icon-split btn-sm service-status float-end">
|
||||
|
@ -50,7 +50,7 @@
|
|||
<div class="card-body">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form role="form" action="hostapd_conf" method="POST" class="needs-validation" novalidate>
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs">
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</div>
|
||||
<div class="text-center mb-4">
|
||||
<form id="admin-login-form" action="login" method="POST" class="needs-validation" novalidate>
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<div class="form-group">
|
||||
<input type="hidden" name="login-auth">
|
||||
<input type="hidden" id="redirect-url" name="redirect-url" value="<?php echo htmlspecialchars($redirectUrl, ENT_QUOTES, 'UTF-8'); ?>">
|
||||
|
@ -32,6 +32,7 @@
|
|||
</div>
|
||||
<button type="submit" class="btn btn-outline btn-admin-login rounded-pill w-75 mt-4"><?php echo _("Login") ?></button>
|
||||
<div class="small mt-2"><a href="https://docs.raspap.com/authentication/#restoring-defaults" target="_blank"><?php echo _("Forgot password") ?></a></div>
|
||||
<img src="app/img/uri-qr-code.php?uri=https://docs.raspap.com/authentication/" class="figure-img img-fluid mt-2" alt="RaspAP docs" style="width:75px;">
|
||||
</form>
|
||||
</div>
|
||||
</div><!-- /.col -->
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<div class="card-body">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form role="form" action="openvpn_conf" enctype="multipart/form-data" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item"><a class="nav-link active" id="clienttab" href="#openvpnclient" data-bs-toggle="tab"><?php echo _("Client settings"); ?></a></li>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<div class="card-body">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form role="form" action="provider_conf" enctype="multipart/form-data" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item"><a class="nav-link active" id="clienttab" href="#providerclient" data-bs-toggle="tab"><?php echo _("Settings"); ?></a></li>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<div class="card-body">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form role="form" action="restapi_conf" method="POST" class="needs-validation" novalidate>
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item"><a class="nav-link active" id="restapisettingstab" href="#restapisettings" data-bs-toggle="tab"><?php echo _("Settings"); ?></a></li>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<div class="card-body">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form role="form" action="system_info" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="nav-item"><a class="nav-link active" id="basictab" href="#basic" aria-controls="basic" role="tab" data-bs-toggle="tab"><?php echo _("Basic"); ?></a></li>
|
||||
<li role="presentation" class="nav-item"><a class="nav-link" id="languagetab" href="#language" aria-controls="language" role="tab" data-bs-toggle="tab"><?php echo _("Language"); ?></a></li>
|
||||
|
@ -151,6 +151,10 @@
|
|||
<td><small><code><span id="plugin-configuration" class="mb-0"></span></code></small></td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo _("Signed Packages"); ?></th>
|
||||
<td><small><code><span id="plugin-packages" class="mb-0"></span></code></small></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo _("Dependencies"); ?></th>
|
||||
<td><small><code><span id="plugin-dependencies" class="mb-0"></span></code></small></td>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<h4 class="mt-3"><?php echo _("Advanced settings") ;?></h4>
|
||||
<?php if (!RASPI_MONITOR_ENABLED) : ?>
|
||||
<form action="system_info" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<div class="row">
|
||||
<div class="mb-3 col-md-6">
|
||||
<label for="code"><?php echo _("Web server port") ;?></label>
|
||||
|
|
|
@ -9,6 +9,9 @@ include('includes/sysstats.php');
|
|||
<div class="col-lg-6">
|
||||
<h4 class="mt-3"><?php echo _("System Information"); ?></h4>
|
||||
<div class="row ms-1">
|
||||
<div class="col-4">
|
||||
<img class="device-illustration mx-3 my-2" src="app/img/devices/<?php echo $deviceImage; ?>" alt="<?php echo htmlspecialchars($revision, ENT_QUOTES); ?>"></a>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<div class="row mb-1">
|
||||
<div class="info-item col-4"><?php echo _("Hostname"); ?></div><div class="info-value col"><?php echo htmlspecialchars($hostname, ENT_QUOTES); ?></div>
|
||||
|
@ -53,7 +56,7 @@ include('includes/sysstats.php');
|
|||
</div>
|
||||
|
||||
<form action="system_info" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<?php if (!RASPI_MONITOR_ENABLED) : ?>
|
||||
<input type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#system-confirm-reboot" value="<?php echo _("Reboot"); ?>" />
|
||||
<input type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#system-confirm-shutdown" value="<?php echo _("Shutdown"); ?>" />
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!-- plugins tab -->
|
||||
<div role="tabpanel" class="tab-pane" id="plugins">
|
||||
<h4 class="mt-3"><?php echo _("Plugins") ;?></h4>
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<div class="row">
|
||||
<div class="form-group col-lg-8 col-md-8">
|
||||
<label>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<form action="system_info" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<button type="button" onClick="window.location.reload();" class="btn btn-outline btn-primary"><i class="fas fa-sync-alt"></i> <?php echo _("Refresh") ?></a>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div role="tabpanel" class="tab-pane" id="tools">
|
||||
<h4 class="mt-3"><?php echo _("System tools") ;?></h4>
|
||||
<?php if (!RASPI_MONITOR_ENABLED) : ?>
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
|
||||
<div class="row">
|
||||
<div class="mb-3 col-lg-8 col-md-8">
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
<input class="form-check-input" id="wgLogEnable" type="checkbox" name="wgLogEnable" value="1" <?php echo $optLogEnable ? ' checked="checked"' : "" ?> aria-describedby="wgLogEnable">
|
||||
<label class="form-check-label" for="wgLogEnable"><?php echo _("Logfile output") ?></label>
|
||||
</div>
|
||||
<?php
|
||||
exec('sudo chmod o+r /tmp/wireguard.log');
|
||||
$log = file_get_contents('/tmp/wireguard.log');
|
||||
echo '<textarea class="logoutput text-secondary my-3">'.htmlspecialchars($log, ENT_QUOTES).'</textarea>';
|
||||
<?php echo '<textarea class="logoutput text-secondary my-3">'.htmlspecialchars($wg_log, ENT_QUOTES).'</textarea>';
|
||||
?>
|
||||
</div>
|
||||
</div><!-- /.row -->
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<div class="card-body">
|
||||
<?php $status->showMessages(); ?>
|
||||
<form role="form" action="wg_conf" enctype="multipart/form-data" method="POST">
|
||||
<?php echo CSRFTokenFieldTag() ?>
|
||||
<?php echo \RaspAP\Tokens\CSRF::hiddenField(); ?>
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="nav-item"><a class="nav-link active" id="settingstab" href="#wgsettings" data-bs-toggle="tab"><?php echo _("Settings"); ?></a></li>
|
||||
|
|
Loading…
Add table
Reference in a new issue