diff --git a/README.md b/README.md index 4950b4f4..34b28953 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@  -# `$ raspap-webgui` [](https://github.com/billz/raspap-webgui/releases) [](https://github.com/thibmaek/awesome-raspberry-pi) +# `$ raspap-webgui` [](https://github.com/billz/raspap-webgui/releases) [](https://github.com/thibmaek/awesome-raspberry-pi) [](https://beerpay.io/billz/raspap-webgui) + A simple, responsive web interface to control wifi, hostapd and related services on the Raspberry Pi. This project was inspired by a [**blog post**](http://sirlagz.net/2013/02/06/script-web-configuration-page-for-raspberry-pi/) by SirLagz about using a web page rather than ssh to configure wifi and hostapd settings on the Raspberry Pi. I mostly just prettified the UI by wrapping it in [**SB Admin 2**](https://github.com/BlackrockDigital/startbootstrap-sb-admin-2), a Bootstrap based admin theme. Since then, the project has evolved to include greater control over many aspects of a networked RPi, better security, authentication, a Quick Installer, support for themes and more. RaspAP has been featured on sites such as [Instructables](http://www.instructables.com/id/Raspberry-Pi-As-Completely-Wireless-Router/), [Adafruit](https://blog.adafruit.com/2016/06/24/raspap-wifi-configuration-portal-piday-raspberrypi-raspberry_pi/), [Raspberry Pi Weekly](https://www.raspberrypi.org/weekly/commander/) and [Awesome Raspberry Pi](https://project-awesome.org/thibmaek/awesome-raspberry-pi) and implemented in countless projects. @@ -53,7 +54,7 @@ configured as an access point as follows: ## Manual installation These steps apply to the latest release of Raspbian (currently [Stretch](https://www.raspberrypi.org/downloads/raspbian/)). Notes for previously released versions are provided, where applicable. Start off by installing git, lighttpd, php7, hostapd and dnsmasq. ```sh -$ sudo apt-get install git lighttpd php7.0-cgi hostapd dnsmasq +$ sudo apt-get install git lighttpd php7.0-cgi hostapd dnsmasq vnstat ``` **Note:** for Raspbian Jessie and Wheezy, replace `php7.0-cgi` with `php5-cgi`. After that, enable PHP for lighttpd and restart it for the settings to take effect. ```sh diff --git a/ajax/bandwidth/get_bandwidth.php b/ajax/bandwidth/get_bandwidth.php new file mode 100644 index 00000000..ea0c103e --- /dev/null +++ b/ajax/bandwidth/get_bandwidth.php @@ -0,0 +1,85 @@ + 0) { + $interface = $interfacesWlo[0]; + } else { + exit('No network interfaces found.'); + } +} + +define('IFNAMSIZ', 16); +if (strlen($interface) > IFNAMSIZ) { + exit('Interface name too long.'); +} elseif(!preg_match('/^[a-zA-Z0-9]+$/', $interface)) { + exit('Invalid interface name.'); +} + +exec(sprintf('vnstat -i %s --json ', escapeshellarg($interface)), $jsonstdoutvnstat, + $exitcodedaily); +if ($exitcodedaily !== 0) { + exit('vnstat error'); +} + +$jsonobj = json_decode($jsonstdoutvnstat[0], true); +$timeunits = filter_input(INPUT_GET, 'tu'); +if ($timeunits === 'm') { + // months + $jsonData = $jsonobj['interfaces'][0]['traffic']['months']; +} else { + // default: days + $jsonData = $jsonobj['interfaces'][0]['traffic']['days']; +} + +$datasizeunits = filter_input(INPUT_GET, 'dsu'); +header('X-Content-Type-Options: nosniff'); +header('Content-Type: application/json'); +echo '[ '; +$firstelm = true; +for ($i = count($jsonData) - 1; $i >= 0; --$i) { + if ($timeunits === 'm') { + $dt = DateTime::createFromFormat('Y n', $jsonData[$i]['date']['year'].' '. + $jsonData[$i]['date']['month']); + } else { + $dt = DateTime::createFromFormat('Y n j', $jsonData[$i]['date']['year'].' '. + $jsonData[$i]['date']['month'].' '. + $jsonData[$i]['date']['day']); + } + + if ($firstelm) { + $firstelm = false; + } else { + echo ','; + } + + if ($datasizeunits == 'mb') { + $datasend = round($jsonData[$i]['tx'] / 1024, 0); + $datareceived = round($jsonData[$i]['rx'] / 1024, 0); + } else { + $datasend = $jsonData[$i]['rx']; + $datareceived = $jsonData[$i]['rx']; + } + + if ($timeunits === 'm') { + echo '{ "date": "' , $dt->format('Y-m') , '", "rx": "' , $datareceived , + '", "tx": "' , $datasend , '" }'; + } else { + echo '{ "date": "' , $dt->format('Y-m-d') , '", "rx": "' , $datareceived , + '", "tx": "' , $datasend , '" }'; + } +} + +echo ' ]'; + + diff --git a/dist/css/terminal.css b/dist/css/terminal.css index ace1fc60..a62d2667 100644 --- a/dist/css/terminal.css +++ b/dist/css/terminal.css @@ -1,216 +1,216 @@ html * { - font-family: Courier New, Andale Mono, monospace; - font-size: 10pt; - color: #33ff00; + font-family: Courier New, Andale Mono, monospace; + font-size: 10pt; + color: #33ff00; } #page-wrapper { - padding: 0 20px; - border-left: 1px solid #33ff00; + padding: 0 20px; + border-left: 1px solid #33ff00; } .nav>li>a { - font-size: 10pt; + font-size: 10pt; } .nav>li>a:focus, .nav>li>a:hover { - background-color: #000; + background-color: #000; } .nav-tabs>li.active>a, .nav-tabs>li.active>a:focus, .nav-tabs>li.active>a:hover { - color: #33ff00; - cursor: default; - background-color: #000; - border: 1px solid #33ff00; - border-bottom-color: #33ff00; + color: #33ff00; + cursor: default; + background-color: #000; + border: 1px solid #33ff00; + border-bottom-color: #33ff00; } .nav-tabs>li>a,.nav-tabs>li>a:hover { - border: 1px solid #33ff00; + border: 1px solid #33ff00; } .nav-tabs { - border-bottom: 1px solid #33ff00; + border-bottom: 1px solid #33ff00; } .navbar-default { - border-color: #33ff00; + border-color: #33ff00; } .navbar-default .navbar-brand, .navbar-default .navbar-brand:hover { - color: #33ff00; + color: #33ff00; } .navbar-default .navbar-toggle { - border-color: #33ff00; + border-color: #33ff00; } .navbar-default .navbar-toggle .icon-bar { - background-color: #33ff00; + background-color: #33ff00; } .navbar-default .navbar-toggle:focus, .navbar-default .navbar-toggle:hover { - background-color: #000; + background-color: #000; } .logo { - visibility: collapse; - width: 0px; + visibility: collapse; + width: 0px; } a:focus, a:hover { - color: #33ff00; + color: #33ff00; } .panel-primary { - border-color: #33ff00; + border-color: #33ff00; } .panel-primary>.panel-heading, .panel-default>.panel-heading { - border-color: #33ff00; - background-color: #33ff00; - color: #000; - font-size: 12pt; + border-color: #33ff00; + background-color: #33ff00; + color: #000; + font-size: 12pt; } .panel-primary>.panel-heading .fa { - color: #000; + color: #000; } .panel { - margin-bottom: 20px; - border: 1px solid #33ff00; - border-radius: 0px; - background-color: #000; + margin-bottom: 20px; + border: 1px solid #33ff00; + border-radius: 0px; + background-color: #000; } hr { - border-top: 1px solid #33ff00; + border-top: 1px solid #33ff00; } .page-header { - font-size: 24pt; - margin: 10px 0 20px; - border-bottom: 1px solid #33ff00; + font-size: 24pt; + margin: 10px 0 20px; + border-bottom: 1px solid #33ff00; } #wrapper,#page-wrapper,.panel-body,.nav>li>a,.navbar-default { - background-color: #000; + background-color: #000; } .panel-footer { - background-color: #000; - border-top: 1px solid #33ff00; + background-color: #000; + border-top: 1px solid #33ff00; } .panel-primary>.panel-heading::before, .navbar-default::before { - content: " "; - display: block; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06)); - z-index: 2; - background-size: 100% 2px, 3px 100%; - pointer-events: none; + content: " "; + display: block; + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06)); + z-index: 2; + background-size: 100% 2px, 3px 100%; + pointer-events: none; } .sidebar ul li a.active,.sidebar ul li a.hover { - background-color: #000; + background-color: #000; } .sidebar ul li { - border-bottom: 1px solid #33ff00; + border-bottom: 1px solid #33ff00; } .btn-primary.btn-outline,.btn-warning { - color: #33ff00; - border-color: #33ff00; + color: #33ff00; + border-color: #33ff00; } .btn-primary:hover,.btn-primary:focus,.btn-warning:hover,.btn-warning:focus,.btn-primary:active { - color: #33ff00; - background-color: #000; - border-color: #33ff00; + color: #33ff00; + background-color: #000; + border-color: #33ff00; } .btn-primary.btn-outline:hover,.btn-success, .btn-success.btn-outline:hover, .btn-info.btn-outline:hover, .btn-warning.btn-outline:hover, .btn-danger.btn-outline:hover { - color: #33ff00; + color: #33ff00; } label.btn.btn-primary { - color: #33ff00; + color: #33ff00; } label.btn.btn-primary.active, label.btn.btn-warning.active { - background-color: #33ff00; - border-color: #33ff00; - color: #000; + background-color: #33ff00; + border-color: #33ff00; + color: #000; } .label-warning { - background-color: #33ff00; + background-color: #33ff00; } span.label.label-warning { - color: #000; + color: #000; } .btn.btn-primary { - border-color: #33ff00; + border-color: #33ff00; } .table>tbody>tr>td, .table>tbody>tr>th, .table>tfoot>tr>td, .table>tfoot>tr>th, .table>thead>tr>td, .table>thead>tr>th { - background-color: #000; - border-top: 1px solid #000; + background-color: #000; + border-top: 1px solid #000; } .table>thead>tr>th { - vertical-align: bottom; - border-bottom: 1px solid #33ff00; + vertical-align: bottom; + border-bottom: 1px solid #33ff00; } .btn-info, .btn-info:hover, .btn-info[disabled], .btn-danger.disabled, .btn-danger.disabled.active, .btn-danger.disabled.focus, .btn-danger.disabled:active, .btn-danger.disabled:focus, .btn-danger.disabled:hover, .btn-danger[disabled], .btn-danger[disabled].active, .btn-danger[disabled].focus, .btn-danger[disabled]:active, .btn-danger[disabled]:focus, .btn-danger[disabled]:hover, fieldset[disabled] .btn-danger, fieldset[disabled] .btn-danger.active, fieldset[disabled] .btn-danger.focus, fieldset[disabled] .btn-danger:active, fieldset[disabled] .btn-danger:focus, fieldset[disabled] .btn-danger:hover, .btn-info:hover { - background-color: #000; - border-color: #33ff00; - color: #33ff00; + background-color: #000; + border-color: #33ff00; + color: #33ff00; } .btn { - background-color: #000; - border-radius: 0px; + background-color: #000; + border-radius: 0px; } .alert { - border-radius: 0px; + border-radius: 0px; } -.alert-success,.alert-warning,.alert-ifo,.alert-dismissable,.alert-danger { - color: #33ff00; - background-color: #000; - border-color: #33ff00; - border: 1px dashed; +.alert-success,.alert-warning,.alert-info,.alert-dismissable,.alert-danger { + color: #33ff00; + background-color: #000; + border-color: #33ff00; + border: 1px dashed; } .close { - font-size: 18px; - font-weight: normal; - text-shadow: 0 0px 0 #000; - opacity: 1; + font-size: 18px; + font-weight: normal; + text-shadow: 0 0px 0 #000; + opacity: 1; } .form-control, .form-control:focus { - color: #33ff00; - background-color: #000; - border: 1px solid #33ff00; - border-radius: 0px; - transition: unset; + color: #33ff00; + background-color: #000; + border: 1px solid #33ff00; + border-radius: 0px; + transition: unset; } input[type="text"]{ - color: #33ff00 !important + color: #33ff00 !important } .form-control::-webkit-input-placeholder { color: #33ff00; } @@ -220,41 +220,60 @@ input[type="text"]{ .form-control::-ms-input-placeholder { color: #33ff00; } .progress { - background-color: #000; - border-radius: 0px; + background-color: #000; + border-radius: 0px; } .progress-bar { - color: #000; + color: #000; } .info-item { - width: 140px; - float: left; + width: 140px; + float: left; } .logoutput { - width: 100%; - height: 300px; - background-color: #000; - border-color: #33ff00; + width: 100%; + height: 300px; + background-color: #000; + border-color: #33ff00; } .webconsole { - width: 100%; - height: 100%; - border-color: #33ff00; - border-bottom: 1px solid; - border-left: 1px solid; - border-top: 0px; - border-right: 1px solid; + width: 100%; + height: 100%; + border-color: #33ff00; + border-bottom: 1px solid; + border-left: 1px solid; + border-top: 0px; + border-right: 1px solid; } #console { - height: 500px; + height: 500px; } .systemtabcontent { - height: 100%; - min-height: 500px; + height: 100%; + min-height: 500px; +} + +tspan, rect { + fill: #33ff00; +} + +.morris-hover.morris-default-style { + background: none; + border-radius: 0px; + border-color: #33ff00; + border: dashed 1px #33ff00; +} + +.morris-hover-point { + color: #33ff00 !important; +} + +path { + stroke: #33ff00; } diff --git a/includes/authenticate.php b/includes/authenticate.php index 79151a24..d6cd2c6e 100755 --- a/includes/authenticate.php +++ b/includes/authenticate.php @@ -6,7 +6,13 @@ $validated = ($user == $config['admin_user']) && password_verify($pass, $config[ if (!$validated) { header('WWW-Authenticate: Basic realm="RaspAP"'); - header('HTTP/1.0 401 Unauthorized'); - die ("Not authorized"); + if (function_exists('http_response_code')) { + // http_response_code will respond with proper HTTP version back. + http_response_code(401); + } else { + header('HTTP/1.0 401 Unauthorized'); + } + + exit('Not authorized'.PHP_EOL); } diff --git a/includes/config.php b/includes/config.php index 46536280..70f271f8 100755 --- a/includes/config.php +++ b/includes/config.php @@ -26,6 +26,7 @@ define('RASPI_OPENVPN_ENABLED', false ); define('RASPI_TORPROXY_ENABLED', false ); define('RASPI_CONFAUTH_ENABLED', true ); define('RASPI_CHANGETHEME_ENABLED', true ); +define('RASPI_VNSTAT_ENABLED', true ); // Locale settings define('LOCALE_ROOT', 'locale'); diff --git a/includes/data_usage.php b/includes/data_usage.php new file mode 100644 index 00000000..db2e4cb4 --- /dev/null +++ b/includes/data_usage.php @@ -0,0 +1,91 @@ + +