Merge with upstream master

This commit is contained in:
billz 2021-06-05 12:02:26 +01:00
commit 06476b9a61
22 changed files with 428 additions and 223 deletions

View File

@ -17,12 +17,13 @@ You can [become a sponsor](https://github.com/sponsors/RaspAP) using your indivi
### Exclusive features
When backers were asked which feature they'd most like to see added to RaspAP, the ability to manage multiple OpenVPN client configurations topped the list of requests. We think this is a great idea, so we're adding this as the first feature exclusive to insiders.
✅ Multiple OpenVPN client configs
✅ [Multiple OpenVPN client configs](https://docs.raspap.com/openvpn/#multiple-client-configs)
✅ [OpenVPN certificate authentication](https://docs.raspap.com/openvpn/#certificate-authentication)
✅ OpenVPN service logging
✅ Night mode toggle
✅ Restrict network to static clients
✅ WireGuard support
⚙️ Traffic shaping (in progress)
[WireGuard support](https://docs.raspap.com/wireguard/)
✅ [Set AP transmit power](https://docs.raspap.com/ap-basics/#transmit-power)
Look for the list above to grow as we add more exclusive features.
@ -30,22 +31,28 @@ Look for the list above to grow as we add more exclusive features.
Below is a list of funding targets. When a funding target is reached, the features that are tied to it are merged back into RaspAP and released to the public for general availability.
#### $500
✅ Multiple OpenVPN client configs
✅ OpenVPN service logging
✅ Night mode toggle
✅ Restrict network to static clients
✅ WireGuard support
⚙️ Traffic shaping (in progress)
The first **Insiders Edition** includes the exclusive features listed above.
### Frequently asked questions
#### How do I install Insiders?
*How do I install Insiders?*
Invoke the [Quick Installer](https://docs.raspap.com/quick/) with the `--insiders` switch, like so:
```
curl -sL https://install.raspap.com | bash -s -- --insiders
```
This will automatically pull from the private Insiders repo during the installation process.
#### Upgrading
*I have an existing RaspAP installation. How do I upgrade to Insiders?*
Upgrading is easy. Simply invoke the [Quick Installer](https://docs.raspap.com/quick/) with the `--upgrade` switch, specifying the private Insiders repo, like so:
Upgrading is easy. Invoke the [Quick Installer](https://docs.raspap.com/quick/) with the `--upgrade` switch, specifying the private Insiders edition, like so:
```
curl -sL https://install.raspap.com | bash -s -- --upgrade --repo raspap/raspap-insiders
curl -sL https://install.raspap.com | bash -s -- --upgrade --insiders
```
If you haven't [added SSH keys to your GitHub account](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh) you will be prompted to authenticate. If so, just enter your GitHub credentials during the install:

View File

@ -7,7 +7,7 @@ $interface = $_GET['iface'];
if (isset($interface)) {
// fetch dnsmasq.conf settings for interface
exec('cat '. RASPI_DNSMASQ_PREFIX.$interface.'.conf', $return);
exec('cat '. escapeshellarg(RASPI_DNSMASQ_PREFIX.$interface.'.conf'), $return);
$conf = ParseConfig($return);
$dhcpdata['DHCPEnabled'] = empty($conf) ? false : true;

View File

@ -15,4 +15,8 @@ nearbyWifiStations($networks, !isset($_REQUEST["refresh"]));
connectedWifiStations($networks);
sortNetworksByRSSI($networks);
echo renderTemplate('wifi_stations', compact('networks'), true);
$connected = array_filter($networks, function($n) { return $n['connected']; } );
$known = array_filter($networks, function($n) { return !$n['connected'] && $n['configured']; } );
$nearby = array_filter($networks, function($n) { return !$n['configured']; } );
echo renderTemplate('wifi_stations', compact('networks', 'connected', 'known', 'nearby'), true);

View File

@ -16,6 +16,11 @@ body {
color: #212529;
}
.h-underlined {
border-bottom: 1px solid #e3e6f0;
padding-bottom: 0.3rem;
}
.page-header {
margin: 20px 0 20px;
}
@ -32,7 +37,6 @@ body {
.row { margin-left: 0rem; margin-right: 0rem; }
.col-lg-12 { padding-right: 0.25rem; padding-left: 0.25rem; }
.form-group.col-md-6 { margin-left: -0.5rem; }
.js-wifi-stations { margin-left: -0.5rem; margin-right: -0.5rem; }
h4.mt-3 { margin-left: 0.5rem; }
}
@ -141,6 +145,7 @@ i.fa.fa-bars:hover{
.service-status {
border-width: 0;
align-items: center;
}
.service-status-up {
@ -190,8 +195,12 @@ pre.unstyled {
width: 100%;
}
.js-reload-wifi-stations {
min-width: 10rem;
@media (min-width: 576px) {
.card-grid {
display: grid;
grid-template-columns: minmax(0, 1fr) 50%;
grid-gap: 1rem;
}
}
.sidebar.toggled .nav-item .nav-link span {

View File

@ -8,7 +8,6 @@ License: GNU General Public License v3.0
html * {
font-family: Verdana, Geneva, sans-serif;
font-size: 0.9rem;
color: #828282;
}
@ -34,6 +33,11 @@ h5.card-title {
color: #212529;
}
.h-underlined {
border-bottom: 1px solid #e3e6f0;
padding-bottom: 0.3rem;
}
.card, .modal-dialog {
border-radius: 1px;
border-color: #ff6600;
@ -115,7 +119,6 @@ ul.nav-tabs, .nav-tabs .nav-link {
.row { margin-left: 0rem; margin-right: 0rem; }
.col-lg-12 { padding-right: 0.25rem; padding-left: 0.25rem; }
.form-group.col-md-6 { margin-left: -0.5rem; }
.js-wifi-stations { margin-left: -0.5rem; margin-right: -0.5rem; }
h4.mt-3 { margin-left: 0.5rem; }
}
@ -180,6 +183,7 @@ ul.nav-tabs, .nav-tabs .nav-link {
.service-status {
border-width: 0;
align-items: center;
}
.service-status-up {
@ -231,8 +235,12 @@ pre.unstyled {
width: 100%;
}
.js-reload-wifi-stations {
min-width: 10rem;
@media (min-width: 576px) {
.card-grid {
display: grid;
grid-template-columns: minmax(0, 1fr) 50%;
grid-gap: 1rem;
}
}
.sidebar.toggled .nav-item .nav-link {

View File

@ -23,6 +23,11 @@ h5.card-title {
font-size: 1.2rem;
}
.h-underlined {
border-bottom: 1px solid #e3e6f0;
padding-bottom: 0.3rem;
}
.page-header {
padding: 0 20px;
border-left: .01rem solid #d2d2d2;
@ -53,7 +58,6 @@ h5.card-title {
.row { margin-left: 0rem; margin-right: 0rem; }
.col-lg-12 { padding-right: 0.25rem; padding-left: 0.25rem; }
.form-group.col-md-6 { margin-left: -0.5rem; }
.js-wifi-stations { margin-left: -0.5rem; margin-right: -0.5rem; }
h4.mt-3 { margin-left: 0.5rem; }
}
@ -374,15 +378,18 @@ tspan, rect {
fill: #d2d2d2;
}
small {
font-size: 80%;
font-weight: 400;
text-muted {
font-size: 0.8rem;
}
.fas.fa-circle {
font-size: 0.5rem;
}
.service-status {
align-items: center;
}
.service-status-up {
color: #a1ec38 !important;
}
@ -416,6 +423,20 @@ pre {
margin-bottom: 0.5em;
}
.loading-spinner {
background: url("../../app/img/loading-spinner.gif") no-repeat scroll center center transparent;
min-height: 150px;
width: 100%;
}
@media (min-width: 576px) {
.card-grid {
display: grid;
grid-template-columns: minmax(0, 1fr) 50%;
grid-gap: 1rem;
}
}
.toggle-off.btn {
padding-left: 1.2rem;
font-size: 0.9rem!important;

View File

@ -28,7 +28,7 @@ $ssid = qr_encode($ssid);
$password = qr_encode($password);
$data = "WIFI:S:$ssid;T:$type;P:$password;$hidden;";
$command = "qrencode -t svg -m 0 -o - " . mb_escapeshellarg($data);
$command = "qrencode -t svg -m 1 -o - " . mb_escapeshellarg($data);
$svg = shell_exec($command);
$config_mtime = filemtime(RASPI_HOSTAPD_CONFIG);

View File

@ -202,8 +202,8 @@ Populates the DHCP server form fields
Option toggles are set dynamically depending on the loaded configuration
*/
function loadInterfaceDHCPSelect() {
var iface = $('#cbxdhcpiface').val();
$.get('ajax/networking/get_netcfg.php?iface='+iface,function(data){
var strInterface = $('#cbxdhcpiface').val();
$.get('ajax/networking/get_netcfg.php?iface='+strInterface,function(data){
jsonData = JSON.parse(data);
$('#dhcp-iface')[0].checked = jsonData.DHCPEnabled;
$('#txtipaddress').val(jsonData.StaticIP);

View File

@ -22,7 +22,8 @@
"208.67.222.222"
],
"Quad9": [
"9.9.9.9"
"9.9.9.9",
"149.112.112.112"
],
"Yandex.DNS": [
"77.88.8.2",

View File

@ -19,6 +19,11 @@ function DisplayWPAConfig()
$result = 0;
exec('sudo wpa_cli -i ' . $_SESSION['wifi_client_interface'] . ' select_network '.strval($_POST['connect']));
$status->addMessage('New network selected', 'success');
} elseif (isset($_POST['wpa_reinit'])) {
$status->addMessage('Reinitializing wpa_supplicant', 'info', false);
$force_remove = true;
$result = reinitializeWPA($force_remove);
$status->addMessage($result, 'info');
} elseif (isset($_POST['client_settings'])) {
$tmp_networks = $networks;
if ($wpa_file = fopen('/tmp/wifidata', 'w')) {
@ -93,10 +98,6 @@ function DisplayWPAConfig()
}
}
nearbyWifiStations($networks);
connectedWifiStations($networks);
sortNetworksByRSSI($networks);
$clientInterface = $_SESSION['wifi_client_interface'];
exec('ip a show '.$clientInterface, $stdoutIp);

View File

@ -603,11 +603,10 @@ function mb_escapeshellarg($arg)
{
$isWindows = strtolower(substr(PHP_OS, 0, 3)) === 'win';
if ($isWindows) {
$escaped_arg = str_replace(array('"', '%'), '', $arg);
return '"' . str_replace(array('"', '%'), '', $arg) . '"';
} else {
$escaped_arg = str_replace("'", "'\\''", $arg);
return "'" . str_replace("'", "'\\''", $arg) . "'";
}
return "\"$escaped_arg\"";
}
function dnsServers()
@ -776,3 +775,11 @@ function qr_encode($str)
{
return preg_replace('/(?<!\\\)([\":;,])/', '\\\\\1', $str);
}
function evalHexSequence($string) {
$evaluator = function ($input) {
return hex2bin($input[1]);
};
return preg_replace_callback('/\\\x(..)/', $evaluator, $string);
}

View File

@ -64,9 +64,8 @@ function DisplayHostAPDConfig()
}
}
}
exec('cat '. RASPI_HOSTAPD_CONFIG, $hostapdconfig);
exec('iwgetid '. $_POST['interface'].' -r', $wifiNetworkID);
exec('iwgetid '. escapeshellarg($_POST['interface']). ' -r', $wifiNetworkID);
if (!empty($wifiNetworkID[0])) {
$managedModeEnabled = true;
}
@ -231,11 +230,14 @@ function SaveHostAPDConfig($wpa_array, $enc_types, $modes, $interfaces, $status)
$good_input = false;
}
if ($_POST['wpa'] !== 'none'
&& (strlen($_POST['wpa_passphrase']) < 8 || strlen($_POST['wpa_passphrase']) > 63)
) {
# NB: A pass-phrase is a sequence of between 8 and 63 ASCII-encoded characters (IEEE Std. 802.11i-2004)
# Each character in the pass-phrase must have an encoding in the range of 32 to 126 (decimal). (IEEE Std. 802.11i-2004, Annex H.4.1)
if ($_POST['wpa'] !== 'none' && (strlen($_POST['wpa_passphrase']) < 8 || strlen($_POST['wpa_passphrase']) > 63)) {
$status->addMessage('WPA passphrase must be between 8 and 63 characters', 'danger');
$good_input = false;
} elseif (!ctype_print($_POST['wpa_passphrase'])) {
$status->addMessage('WPA passphrase must be comprised of printable ASCII characters', 'danger');
$good_input = false;
}
if (isset($_POST['hiddenSSID'])) {

View File

@ -18,6 +18,7 @@ function knownWifiStations(&$networks)
switch (strtolower($lineArr[0])) {
case 'ssid':
$ssid = trim($lineArr[1], '"');
$network['ssid'] = $ssid;
break;
case 'psk':
if (array_key_exists('passphrase', $network)) {
@ -69,17 +70,22 @@ function nearbyWifiStations(&$networks, $cached = true)
foreach (explode("\n", $scan_results) as $network) {
$arrNetwork = preg_split("/[\t]+/", $network); // split result into array
if (!array_key_exists(4, $arrNetwork) ||
trim($arrNetwork[4]) == $ap_ssid) {
$ssid = trim($arrNetwork[4]);
$ssid = evalHexSequence($ssid);
// exclude raspap ssid
if (empty($ssid) || $ssid == $ap_ssid) {
continue;
}
$ssid = trim($arrNetwork[4]);
// filter SSID string: anything invisible in 7bit ASCII or quotes -> ignore network
if (preg_match('[\x00-\x1f\x7f-\xff\'\`\´\"]', $ssid)) {
// filter SSID string: unprintable 7bit ASCII control codes, delete or quotes -> ignore network
if (preg_match('[\x00-\x1f\x7f\'\`\´\"]', $ssid)) {
continue;
}
$networks[$ssid]['ssid'] = $ssid;
// If network is saved
if (array_key_exists($ssid, $networks)) {
$networks[$ssid]['visible'] = true;
@ -157,4 +163,20 @@ function getWifiInterface()
}
}
?>
/*
* Reinitializes wpa_supplicant for the wireless client interface
* The 'force' parameter deletes the socket in /var/run/wpa_supplicant/
*
* @param boolean $force
*/
function reinitializeWPA($force)
{
if ($force == true) {
$cmd = escapeshellcmd("sudo /bin/rm /var/run/wpa_supplicant/".$_SESSION['wifi_client_interface']);
$result = exec($cmd);
}
$cmd = escapeshellcmd("sudo /sbin/wpa_supplicant -B -Dnl80211 -c/etc/wpa_supplicant/wpa_supplicant.conf -i". $_SESSION['wifi_client_interface']);
$result = shell_exec($cmd);
return $result;
}

View File

@ -65,14 +65,14 @@ function _install_raspap() {
# search for optional installation files names install_feature_*.sh
function _install_mobile_clients() {
if [ "$insiders" == 1 ]; then
echo -n "Installing support for mobile data clients"
_install_log "Installing support for mobile data clients"
for feature in $(ls $webroot_dir/installers/install_feature_*.sh) ; do
source $feature
f=$(basename $feature)
func="_${f%.*}"
if declare -f -F $func > /dev/null; then
_install_log "Installing $func"
$func || _install_status 1 "Not able to install feature ($func)"
echo "Installing $func"
$func || _install_status 1 "Unable to install feature ($func)"
else
_install_status 1 "Install file $f is missing install function $func"
fi
@ -213,7 +213,7 @@ function _create_hostapd_scripts() {
# Move service control shell scripts
sudo cp "$webroot_dir/installers/"service*.sh "$raspap_dir/hostapd" || _install_status 1 "Unable to move service control scripts"
# Make enablelog.sh and disablelog.sh not writable by www-data group.
sudo chown -c root:"$raspap_user" "$raspap_dir/hostapd/"*.sh || _install_status 1 "Unable change owner and/or group"
sudo chown -c root:root "$raspap_dir/hostapd/"*.sh || _install_status 1 "Unable change owner and/or group"
sudo chmod 750 "$raspap_dir/hostapd/"*.sh || _install_status 1 "Unable to change file permissions"
_install_status 0
}
@ -228,7 +228,7 @@ function _create_lighttpd_scripts() {
sudo cp "$webroot_dir/installers/"configport.sh "$raspap_dir/lighttpd" || _install_status 1 "Unable to move service control scripts"
# Make configport.sh writable by www-data group
echo "Changing file ownership"
sudo chown -c root:"$raspap_user" "$raspap_dir/lighttpd/"*.sh || _install_status 1 "Unable change owner and/or group"
sudo chown -c root:root "$raspap_dir/lighttpd/"*.sh || _install_status 1 "Unable change owner and/or group"
sudo chmod 750 "$raspap_dir/lighttpd/"*.sh || _install_status 1 "Unable to change file permissions"
_install_status 0
}
@ -310,8 +310,9 @@ function _install_adblock() {
echo "Moving and setting permissions for blocklist update script"
sudo cp "$webroot_dir/installers/"update_blocklist.sh "$raspap_dir/adblock" || _install_status 1 "Unable to move blocklist update script"
# Make blocklists and update script writable by www-data group
sudo chown -c root:"$raspap_user" "$raspap_dir/adblock/"*.* || _install_status 1 "Unable to change owner/group"
# Make blocklists writable by www-data group, restrict update scripts to root
sudo chown -c root:"$raspap_user" "$raspap_dir/adblock/"*.txt || _install_status 1 "Unable to change owner/group"
sudo chown -c root:root "$raspap_dir/adblock/"*.sh || _install_status 1 "Unable to change owner/group"
sudo chmod 750 "$raspap_dir/adblock/"*.sh || install_error "Unable to change file permissions"
# Create 090_adblock.conf and write values to /etc/dnsmasq.d
@ -376,7 +377,7 @@ function _install_wireguard() {
echo 'deb http://ftp.debian.org/debian buster-backports main' | sudo tee /etc/apt/sources.list.d/buster-backports.list || _install_status 1 "Unable to add Debian backports repo"
fi
echo "Installing wireguard from apt"
sudo apt-get update && sudo apt-get install $apt_option wireguard || _install_status 1 "Unable to install wireguard"
sudo apt-get install -y wireguard || _install_status 1 "Unable to install wireguard"
echo "Enabling wg-quick@wg0"
sudo systemctl enable wg-quick@wg0 || _install_status 1 "Failed to enable wg-quick service"
echo "Enabling WireGuard management option"
@ -400,11 +401,11 @@ function _create_openvpn_scripts() {
_install_log "Creating OpenVPN control scripts"
sudo mkdir $raspap_dir/openvpn || _install_status 1 "Unable to create directory '$raspap_dir/openvpn'"
# Move service auth control & logging shell scripts
# Move service auth control & logging shell scripts
sudo cp "$webroot_dir/installers/"configauth.sh "$raspap_dir/openvpn" || _install_status 1 "Unable to move auth control script"
sudo cp "$webroot_dir/installers/"openvpnlog.sh "$raspap_dir/openvpn" || _install_status 1 "Unable to move logging script"
# Make scripts executable by www-data group
sudo chown -c root:"$raspap_user" "$raspap_dir/openvpn/"*.sh || _install_status 1 "Unable change owner and/or group"
# Restrict script execution to root user
sudo chown -c root:root "$raspap_dir/openvpn/"*.sh || _install_status 1 "Unable change owner and/or group"
sudo chmod 750 "$raspap_dir/openvpn/"*.sh || _install_status 1 "Unable to change file permissions"
_install_status 0
}
@ -490,9 +491,10 @@ function _move_config_file() {
_install_status 1 "'$raspap_dir' directory doesn't exist"
fi
# Copy config file and make writable by www-data group
_install_log "Moving configuration file to $raspap_dir"
sudo cp "$webroot_dir"/raspap.php "$raspap_dir" || _install_status 1 "Unable to move files to '$raspap_dir'"
sudo chown -R $raspap_user:$raspap_user "$raspap_dir" || _install_status 1 "Unable to change file ownership for '$raspap_dir'"
sudo chown -c $raspap_user:"$raspap_user" "$raspap_dir"/raspap.php || _install_status 1 "Unable change owner and/or group"
}
# Set up default configuration
@ -506,8 +508,8 @@ function _default_configuration() {
sudo cp $webroot_dir/config/dhcpcd.conf /etc/dhcpcd.conf || _install_status 1 "Unable to move dhcpcd configuration file"
sudo cp $webroot_dir/config/defaults.json $raspap_network || _install_status 1 "Unable to move defaults.json settings"
echo "Changing file ownership of $raspap_dir"
sudo chown -R $raspap_user:$raspap_user "$raspap_dir" || _install_status 1 "Unable to change file ownership for '$raspap_dir'"
echo "Changing file ownership of ${raspap_network}/defaults.json"
sudo chown $raspap_user:$raspap_user "$raspap_network"/defaults.json || _install_status 1 "Unable to change file ownership for defaults.json"
echo "Checking for existence of /etc/dnsmasq.d"
[ -d /etc/dnsmasq.d ] || sudo mkdir /etc/dnsmasq.d

View File

@ -4,6 +4,8 @@ www-data ALL=(ALL) NOPASSWD:/bin/cat /etc/wpa_supplicant/wpa_supplicant.conf
www-data ALL=(ALL) NOPASSWD:/bin/cat /etc/wpa_supplicant/wpa_supplicant-wlan[0-9].conf
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/wifidata /etc/wpa_supplicant/wpa_supplicant.conf
www-data ALL=(ALL) NOPASSWD:/bin/cp /tmp/wifidata /etc/wpa_supplicant/wpa_supplicant-wlan[0-9].conf
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_supplicant -B -Dnl80211 -c/etc/wpa_supplicant/wpa_supplicant.conf -iwlan[0-9]
www-data ALL=(ALL) NOPASSWD:/bin/rm /var/run/wpa_supplicant/wlan[0-9]
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i wlan[0-9] scan_results
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i wlan[0-9] scan
www-data ALL=(ALL) NOPASSWD:/sbin/wpa_cli -i wlan[0-9] reconfigure

View File

@ -147,9 +147,33 @@ msgstr "Hide"
msgid "Not configured"
msgstr "Not configured"
msgid "Connected"
msgstr "Connected"
msgid "Known"
msgstr "Known"
msgid "Nearby"
msgstr "Nearby"
msgid "<strong>Note:</strong> WEP access points appear as 'Open'. RaspAP does not currently support connecting to WEP"
msgstr "<strong>Note:</strong> WEP access points appear as 'Open'. RaspAP does not currently support connecting to WEP"
msgid "No Wifi stations found"
msgstr "No Wifi stations found"
msgid "Reinitializing wpa_supplicant"
msgstr "Reinitializing wpa_supplicant"
msgid "Click 'Rescan' to search for nearby Wifi stations."
msgstr "Click 'Rescan' to search for nearby Wifi stations."
msgid "Click 'Reinitialize' to force reinitialize <code>wpa_supplicant</code>."
msgstr "Click 'Reinitialize' to force reinitialize <code>wpa_supplicant</code>."
msgid "Reinitialize"
msgstr "Reinitialize"
#: includes/dashboard.php
msgid "Interface Information"
msgstr "Interface Information"

View File

@ -2,7 +2,7 @@
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="row align-items-center">
<div class="col">
<i class="fas fa-wifi mr-2"></i><?php echo _("WiFi client"); ?>
</div>
@ -16,19 +16,23 @@
</div><!-- /.card-header -->
<div class="card-body">
<?php $status->showMessages(); ?>
<div class="row">
<div class="row align-items-center">
<div class="col">
<h4 class="mb-2"><?php echo _("Client settings"); ?></h4>
<h4 class="m-0 text-nowrap"><?php echo _("Client settings"); ?></h4>
</div>
<div class="col-xs mr-3 mb-3">
<button type="button" class="btn btn-info btn-block float-right js-reload-wifi-stations"><?php echo _("Rescan"); ?></button>
<div class="col">
<button type="button" class="btn btn-info float-right js-reload-wifi-stations"><?php echo _("Rescan"); ?></button>
</div>
</div>
<div class="row">
<div class="col">
<form method="POST" action="wpa_conf" name="wpa_conf_form">
<?php echo CSRFTokenFieldTag() ?>
<input type="hidden" name="client_settings" ?>
<div class="js-wifi-stations loading-spinner"></div>
</form>
</div>
</div>
<form method="POST" action="wpa_conf" name="wpa_conf_form" class="row">
<?php echo CSRFTokenFieldTag() ?>
<input type="hidden" name="client_settings" ?>
<div class="row js-wifi-stations w-100 loading-spinner"></div>
</form>
</div><!-- ./ card-body -->
<div class="card-footer"><?php echo _("<strong>Note:</strong> WEP access points appear as 'Open'. RaspAP does not currently support connecting to WEP"); ?></div>
</div><!-- /.card -->

View File

@ -21,65 +21,61 @@
<div role="tabpanel" class="tab-pane active" id="summary">
<h4 class="mt-3"><?php echo _("Internet connection"); ?></h4>
<div class="row">
<div class="col-sm-12">
<div class="card ">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th><?php echo _("Interface"); ?></th>
<th><?php echo _("IP Address"); ?></th>
<th><?php echo _("Gateway"); ?></th>
<th colspan="2"><?php echo _("Internet Access"); ?></th>
</tr>
</thead>
<tbody>
<?php
if (isset($routeInfo["error"]) || empty($routeInfo)) {
echo "<tr><td colspan=5>No route to the internet found</td></tr>";
} else {
foreach($routeInfo as $route) {
echo "<tr>";
echo "<td>".$route["interface"]."</td>";
echo "<td>".$route["ip-address"]."</td>";
echo "<td>".$route["gateway"]."<br>".$route["gw-name"]."</td>";
$status = $route["access-ip"] ? "fa-check" : "fa-times";
echo '<td><i class="fas '.$status.'"></i><br>'.RASPI_ACCESS_CHECK_IP.'</td>';
$status = $route["access-dns"] ? "fa-check" : "fa-times";
echo '<td><i class="fas '.$status.'"></i><br>'.RASPI_ACCESS_CHECK_DNS.'</td>';
echo "</tr>";
}
}
?>
</tbody>
</table>
</div>
<div class="col-sm-12">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th><?php echo _("Interface"); ?></th>
<th><?php echo _("IP Address"); ?></th>
<th><?php echo _("Gateway"); ?></th>
<th colspan="2"><?php echo _("Internet Access"); ?></th>
</tr>
</thead>
<tbody>
<?php if (isset($routeInfo["error"]) || empty($routeInfo)): ?>
<tr><td colspan=5>No route to the internet found</td></tr>
<?php else: ?>
<?php foreach($routeInfo as $route): ?>
<tr>
<td><?php echo $route['interface'] ?></td>
<td><?php echo $route['ip-address'] ?></td>
<td><?php echo $route['gateway'] ?><br><?php $route['gw-name'] ?></td>
<td>
<p class="m-0">
<i class="fas <?php echo $route["access-ip"] ? "fa-check" : "fa-times"; ?>"></i> <?php echo RASPI_ACCESS_CHECK_IP ?>
</p>
<p class="m-0">
<i class="fas <?php echo $route["access-dns"] ? "fa-check" : "fa-times"; ?>"></i> <?php echo RASPI_ACCESS_CHECK_DNS ?>
</p>
</td>
</tr>
<?php endforeach ?>
<?php endif ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<h4 class="mt-3"><?php echo _("Current settings") ?></h4>
<div class="row">
<?php if (!$bridgedEnabled) : // No interface details when bridged ?>
<?php foreach ($interfaces as $if): ?>
<?php $if_quoted = htmlspecialchars($if, ENT_QUOTES) ?>
<div class="col-md-6 mb-3">
<div class="card">
<div class="card-header"><?php echo $if_quoted ?></div>
<div class="card-body">
<pre class="unstyled" id="<?php echo $if_quoted ?>-summary"></pre>
<?php if (!$bridgedEnabled) : // No interface details when bridged ?>
<?php foreach ($interfaces as $if): ?>
<?php $if_quoted = htmlspecialchars($if, ENT_QUOTES) ?>
<div class="col-md mb-3">
<div class="card h-100 w-100">
<div class="card-header"><?php echo $if_quoted ?></div>
<div class="card-body">
<pre class="unstyled" id="<?php echo $if_quoted ?>-summary"></pre>
</div>
</div>
</div>
</div>
</div>
<?php endforeach ?>
<?php endif ?>
<?php endforeach ?>
<?php endif ?>
</div><!-- /.row -->
<div class="col-lg-12">
<div class="row">
<button type="button" onClick="window.location.reload();" class="btn btn-outline btn-primary"><i class="fas fa-sync-alt"></i> <?php echo _("Refresh") ?></a>
</div>
</div>
<button type="button" onClick="window.location.reload();" class="btn btn-outline btn-primary"><i class="fas fa-sync-alt"></i> <?php echo _("Refresh") ?></a>
</div>
<?php $arrMD = file_exists(($f = RASPI_CONFIG."/networking/mobiledata.ini")) ? parse_ini_file($f) : false;
if ($arrMD==false) { $arrMD=[]; $arrMD["pin"]=$arrMD["apn"]=$arrMD["apn_user"]=$arrMD["apn_pw"]=$arrMD["router_user"]=$arrMD["router_pw"]=""; }
@ -197,6 +193,7 @@
</div><!-- /.tab-panel -->
</div>
</div><!-- /.card-body -->
<div class="card-footer"><?php echo _("Information provided by /sys/class/net"); ?></div>
</div><!-- /.card -->
</div><!-- /.col-lg-12 -->

View File

@ -46,6 +46,65 @@
<?php echo $buttons ?>
</form>
<div class="tab-pane active" id="openvpnclient">
<h4 class="mt-3"><?php echo _("Client settings"); ?></h4>
<div class="row">
<div class="col">
<div class="row mb-2">
<div class="col-lg-12 mt-2 mb-2">
<div class="row ml-1">
<div class="info-item col-xs-3"><?php echo _("IPv4 Address"); ?></div>
<div class="info-value col-xs-3"><?php echo htmlspecialchars($public_ip, ENT_QUOTES); ?><a class="text-gray-500" href="https://ipapi.co/<?php echo($public_ip); ?>" target="_blank" rel="noopener noreferrer"><i class="fas fa-external-link-alt ml-2"></i></a></div>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-lg-12">
<label for="code"><?php echo _("Username"); ?></label>
<input type="text" class="form-control" name="authUser" value="<?php echo htmlspecialchars($authUser, ENT_QUOTES); ?>" />
</div>
</div>
<div class="row">
<div class="form-group col-lg-12">
<label for="code"><?php echo _("Password"); ?></label>
<input type="password" class="form-control" name="authPassword" value="<?php echo htmlspecialchars($authPassword, ENT_QUOTES); ?>" />
</div>
</div>
<div class="row">
<div class="form-group col-lg-12">
<div class="custom-file">
<input type="file" class="custom-file-input" name="customFile" id="customFile">
<label class="custom-file-label" for="customFile"><?php echo _("Select OpenVPN configuration file (.ovpn)"); ?></label>
</div>
</div>
</div>
</div><!-- col-->
<div class="col-sm">
<a href="https://go.nordvpn.net/aff_c?offer_id=15&aff_id=36402&url_id=902"><img src="app/img/no-trace-200x200.png" class="float-left mb-3 mt-3"></a>
</div>
</div><!-- main row -->
</div>
<div class="tab-pane fade" id="openvpnlogoutput">
<h4 class="mt-3"><?php echo _("Client log"); ?></h4>
<div class="row">
<div class="form-group col-md-8">
<?php
echo '<textarea class="logoutput"></textarea>';
?>
</div>
</div>
</div>
<?php if (!RASPI_MONITOR_ENABLED) : ?>
<input type="submit" class="btn btn-outline btn-primary" name="SaveOpenVPNSettings" value="Save settings" />
<?php if ($openvpnstatus[0] == 0) {
echo '<input type="submit" class="btn btn-success" name="StartOpenVPN" value="Start OpenVPN" />' , PHP_EOL;
} else {
echo '<input type="submit" class="btn btn-warning" name="StopOpenVPN" value="Stop OpenVPN" />' , PHP_EOL;
}
?>
<?php endif ?>
</form>
</div>
</div><!-- /.card-body -->
<div class="card-footer"><?php echo _("Information provided by openvpn"); ?></div>
</div><!-- /.card -->

View File

@ -8,9 +8,19 @@ include('includes/sysstats.php');
<div class="row">
<div class="col-lg-6">
<h4 class="mt-3"><?php echo _("System Information"); ?></h4>
<div class="info-item"><?php echo _("Hostname"); ?></div><div><?php echo htmlspecialchars($hostname, ENT_QUOTES); ?></div>
<div class="info-item"><?php echo _("Pi Revision"); ?></div><div><?php echo htmlspecialchars(RPiVersion(), ENT_QUOTES); ?></div>
<div class="info-item"><?php echo _("Uptime"); ?></div><div><?php echo htmlspecialchars($uptime, ENT_QUOTES); ?></div>
<div class="row ml-1">
<div class="col-sm">
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Hostname"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($hostname, ENT_QUOTES); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Pi Revision"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars(RPiVersion(), ENT_QUOTES); ?></div>
</div>
<div class="row mb-1">
<div class="info-item col-xs-3"><?php echo _("Uptime"); ?></div><div class="info-value col-xs-3"><?php echo htmlspecialchars($uptime, ENT_QUOTES); ?></div>
</div>
</div>
</div>
<div class="mb-1"><?php echo _("Memory Used"); ?></div>
<div class="progress mb-2" style="height: 20px;">
<div class="progress-bar bg-<?php echo htmlspecialchars($memused_status, ENT_QUOTES); ?>"

View File

@ -1,105 +1,47 @@
<?php if (empty($networks)) { ?>
<?php if (empty($networks)): ?>
<div class="col-md-6 ml-6">
<p class="lead text-center"><?php echo _('No Wifi stations found') ?></p>
<p class="text-center"><?php echo _('Click "Rescan" to search for nearby Wifi stations.') ?></p>
<p class="text-center"><?php echo _("Click 'Rescan' to search for nearby Wifi stations.") ?></p>
<?php if (!RASPI_MONITOR_ENABLED) : ?>
<p class="text-center"><?php echo _("Click 'Reinitialize' to force reinitialize <code>wpa_supplicant</code>.") ?></p>
<form method="POST" action="wpa_conf" name="wpa_conf_form" class="row">
<?php echo CSRFTokenFieldTag() ?>
<div class="col-xs mr-3 mb-3">
<input type="submit" class="btn btn-warning btn-block float-right" name="wpa_reinit" value="<?php echo _("Re-initialize"); ?>" />
</div>
</form>
<?php endif ?>
</div>
<?php } elseif (count($networks) == 1) {
$prop_col = "col-sm-12";
$prop_w = "w-50";
} else {
$prop_col = "col-sm-6";
$prop_w = "w-100";
}
?>
<?php endif ?>
<?php $index = 0; ?>
<div class="row ml-1 mr-1 w-100">
<?php foreach ($networks as $ssid => $network) : ?>
<div class="<?php echo $prop_col; ?> align-items-stretch mb-3">
<div class="card h-100 <?php echo $prop_w; ?>">
<div class="card-body">
<input type="hidden" name="ssid<?php echo $index ?>" value="<?php echo htmlentities($ssid, ENT_QUOTES) ?>" />
<?php if (strlen($ssid) == 0) {
$ssid = "(unknown)";
} ?>
<h5 class="card-title"><?php echo htmlspecialchars($ssid, ENT_QUOTES); ?></h5>
<div class="info-item-wifi"><?php echo _("Status"); ?></div>
<div>
<?php if ($network['configured']) { ?>
<i class="fas fa-check-circle"></i>
<?php } ?>
<?php if ($network['connected']) { ?>
<i class="fas fa-exchange-alt"></i>
<?php } ?>
<?php if (!$network['configured'] && !$network['connected']) {
echo _("Not configured");
} ?>
</div>
<?php if (!empty($connected)): ?>
<h4 class="h-underlined my-3"><?php echo _("Connected") ?></h4>
<div class="card-grid">
<?php foreach ($connected as $network) : ?>
<?php echo renderTemplate("wifi_stations/network", compact('network', 'index')) ?>
<?php $index++; ?>
<?php endforeach ?>
</div>
<?php endif ?>
<div class="info-item-wifi"><?php echo _("Channel"); ?></div>
<div>
<?php if ($network['visible']) { ?>
<?php echo htmlspecialchars($network['channel'], ENT_QUOTES) ?>
<?php } else { ?>
<span class="label label-warning"> X </span>
<?php } ?>
</div>
<div class="info-item-wifi"><?php echo _("RSSI"); ?></div>
<div>
<?php
if (isset($network['RSSI']) && $network['RSSI'] >= -200) {
echo htmlspecialchars($network['RSSI'], ENT_QUOTES);
echo "dB (";
if ($network['RSSI'] >= -50) {
echo 100;
} elseif ($network['RSSI'] <= -100) {
echo 0;
} else {
echo 2*($network['RSSI'] + 100);
}
echo "%)";
} else {
echo " not found ";
}
?>
</div>
<?php if (array_key_exists('priority', $network)) { ?>
<input type="hidden" name="priority<?php echo $index ?>" value="<?php echo htmlspecialchars($network['priority'], ENT_QUOTES); ?>" />
<?php } ?>
<input type="hidden" name="protocol<?php echo $index ?>" value="<?php echo htmlspecialchars($network['protocol'], ENT_QUOTES); ?>" />
<div class="info-item-wifi"><?php echo _("Security"); ?></div>
<div><?php echo $network['protocol'] ?></div>
<div class="form-group">
<div class="info-item-wifi"><?php echo _("Passphrase"); ?></div>
<div class="input-group">
<?php if ($network['protocol'] === 'Open') { ?>
<input type="password" disabled class="form-control" aria-describedby="passphrase" name="passphrase<?php echo $index ?>" value="" />
<?php } else { ?>
<input type="password" class="form-control js-validate-psk" aria-describedby="passphrase" name="passphrase<?php echo $index ?>" value="<?php echo $network['passphrase'] ?>" data-target="#update<?php echo $index ?>" data-colors="#ffd0d0,#d0ffd0">
<div class="input-group-append">
<button class="btn btn-outline-secondary js-toggle-password" type="button" data-target="[name=passphrase<?php echo $index ?>]" data-toggle-with="<?php echo _("Hide") ?>">Show</button>
</div>
<?php } ?>
</div>
</div>
<div class="btn-group btn-block ">
<?php if ($network['configured']) { ?>
<input type="submit" class="col-xs-4 col-md-4 btn btn-warning" value="<?php echo _("Update"); ?>" id="update<?php echo $index ?>" name="update<?php echo $index ?>"<?php echo ($network['protocol'] === 'Open' ? ' disabled' : '')?> data-toggle="modal" data-target="#configureClientModal" />
<button type="submit" class="col-xs-4 col-md-4 btn btn-info" value="<?php echo $index?>" name="connect"><?php echo _("Connect"); ?></button>
<?php } else { ?>
<input type="submit" class="col-xs-4 col-md-4 btn btn-info" value="<?php echo _("Add"); ?>" id="update<?php echo $index ?>" name="update<?php echo $index ?>" <?php echo ($network['protocol'] === 'Open' ? '' : ' disabled')?> data-toggle="modal" data-target="#configureClientModal" />
<?php } ?>
<input type="submit" class="col-xs-4 col-md-4 btn btn-danger" value="<?php echo _("Delete"); ?>" name="delete<?php echo $index ?>"<?php echo ($network['configured'] ? '' : ' disabled')?> data-toggle="modal" data-target="#configureClientModal" />
</div><!-- /.btn-group -->
</div><!-- /.card-body -->
</div><!-- /.card -->
</div><!-- /.col-sm -->
<?php $index += 1; ?>
<?php endforeach ?>
</div><!-- /.row -->
<?php if (!empty($known)): ?>
<h4 class="h-underlined my-3"><?php echo _("Known") ?></h4>
<div class="card-grid">
<?php foreach ($known as $network) : ?>
<?php echo renderTemplate("wifi_stations/network", compact('network', 'index')) ?>
<?php $index++; ?>
<?php endforeach ?>
</div>
<?php endif ?>
<?php if (!empty($nearby)): ?>
<h4 class="h-underlined my-3"><?php echo _("Nearby") ?></h4>
<div class="card-grid">
<?php foreach ($nearby as $network) : ?>
<?php echo renderTemplate("wifi_stations/network", compact('network', 'index')) ?>
<?php $index++; ?>
<?php endforeach ?>
</div>
<?php endif ?>

View File

@ -0,0 +1,83 @@
<div class="card">
<div class="card-body">
<input type="hidden" name="ssid<?php echo $index ?>" value="<?php echo htmlentities($network['ssid'], ENT_QUOTES) ?>" />
<?php if (strlen($network['ssid']) == 0) {
$network['ssid'] = "(unknown)";
} ?>
<h5 class="card-title"><?php echo htmlspecialchars($network['ssid'], ENT_QUOTES); ?></h5>
<div class="info-item-wifi"><?php echo _("Status"); ?></div>
<div>
<?php if ($network['configured']) { ?>
<i class="fas fa-check-circle"></i>
<?php } ?>
<?php if ($network['connected']) { ?>
<i class="fas fa-exchange-alt"></i>
<?php } ?>
<?php if (!$network['configured'] && !$network['connected']) {
echo _("Not configured");
} ?>
</div>
<div class="info-item-wifi"><?php echo _("Channel"); ?></div>
<div>
<?php if ($network['visible']) { ?>
<?php echo htmlspecialchars($network['channel'], ENT_QUOTES) ?>
<?php } else { ?>
<span class="label label-warning"> X </span>
<?php } ?>
</div>
<div class="info-item-wifi"><?php echo _("RSSI"); ?></div>
<div>
<?php
if (isset($network['RSSI']) && $network['RSSI'] >= -200) {
echo htmlspecialchars($network['RSSI'], ENT_QUOTES);
echo "dB (";
if ($network['RSSI'] >= -50) {
echo 100;
} elseif ($network['RSSI'] <= -100) {
echo 0;
} else {
echo 2*($network['RSSI'] + 100);
}
echo "%)";
} else {
echo " not found ";
}
?>
</div>
<?php if (array_key_exists('priority', $network)) { ?>
<input type="hidden" name="priority<?php echo $index ?>" value="<?php echo htmlspecialchars($network['priority'], ENT_QUOTES); ?>" />
<?php } ?>
<input type="hidden" name="protocol<?php echo $index ?>" value="<?php echo htmlspecialchars($network['protocol'], ENT_QUOTES); ?>" />
<div class="info-item-wifi"><?php echo _("Security"); ?></div>
<div><?php echo empty($network['protocol']) ? "-" : $network['protocol'] ?></div>
<div class="form-group">
<div class="info-item-wifi"><?php echo _("Passphrase"); ?></div>
<div class="input-group">
<?php if ($network['protocol'] === 'Open') { ?>
<input type="password" disabled class="form-control" aria-describedby="passphrase" name="passphrase<?php echo $index ?>" value="" />
<?php } else { ?>
<input type="password" class="form-control js-validate-psk" aria-describedby="passphrase" name="passphrase<?php echo $index ?>" value="<?php echo $network['passphrase'] ?>" data-target="#update<?php echo $index ?>" data-colors="#ffd0d0,#d0ffd0">
<div class="input-group-append">
<button class="btn btn-outline-secondary js-toggle-password" type="button" data-target="[name=passphrase<?php echo $index ?>]" data-toggle-with="<?php echo _("Hide") ?>">Show</button>
</div>
<?php } ?>
</div>
</div>
<div class="btn-group btn-block ">
<?php if ($network['configured']) { ?>
<input type="submit" class="col-xs-4 col-md-4 btn btn-warning" value="<?php echo _("Update"); ?>" id="update<?php echo $index ?>" name="update<?php echo $index ?>"<?php echo ($network['protocol'] === 'Open' ? ' disabled' : '')?> data-toggle="modal" data-target="#configureClientModal" />
<button type="submit" class="col-xs-4 col-md-4 btn btn-info" value="<?php echo $index?>" name="connect"><?php echo _("Connect"); ?></button>
<?php } else { ?>
<input type="submit" class="col-xs-4 col-md-4 btn btn-info" value="<?php echo _("Add"); ?>" id="update<?php echo $index ?>" name="update<?php echo $index ?>" <?php echo ($network['protocol'] === 'Open' ? '' : ' disabled')?> data-toggle="modal" data-target="#configureClientModal" />
<?php } ?>
<input type="submit" class="col-xs-4 col-md-4 btn btn-danger" value="<?php echo _("Delete"); ?>" name="delete<?php echo $index ?>"<?php echo ($network['configured'] ? '' : ' disabled')?> data-toggle="modal" data-target="#configureClientModal" />
</div><!-- /.btn-group -->
</div><!-- /.card-body -->
</div><!-- /.card -->