Browse Source

Merge remote-tracking branch 'upstream/dev' into dev

webui
Sebastiaan Jansen 6 years ago
parent
commit
7aeba88771
23 changed files with 13343 additions and 13300 deletions
  1. +6
    -2
      code/espurna/config/defaults.h
  2. +4
    -1
      code/espurna/config/general.h
  3. +3
    -0
      code/espurna/config/prototypes.h
  4. BIN
      code/espurna/data/index.all.html.gz
  5. BIN
      code/espurna/data/index.light.html.gz
  6. BIN
      code/espurna/data/index.rfbridge.html.gz
  7. BIN
      code/espurna/data/index.rfm69.html.gz
  8. BIN
      code/espurna/data/index.sensor.html.gz
  9. BIN
      code/espurna/data/index.small.html.gz
  10. +1
    -1
      code/espurna/ota.ino
  11. +2262
    -2262
      code/espurna/static/index.all.html.gz.h
  12. +2210
    -2210
      code/espurna/static/index.light.html.gz.h
  13. +1858
    -1858
      code/espurna/static/index.rfbridge.html.gz.h
  14. +3224
    -3224
      code/espurna/static/index.rfm69.html.gz.h
  15. +1879
    -1879
      code/espurna/static/index.sensor.html.gz.h
  16. +1844
    -1844
      code/espurna/static/index.small.html.gz.h
  17. +28
    -2
      code/espurna/telnet.ino
  18. +4
    -0
      code/espurna/utils.ino
  19. +2
    -2
      code/espurna/web.ino
  20. +2
    -2
      code/espurna/wifi.ino
  21. +1
    -2
      code/espurna/ws.ino
  22. +9
    -5
      code/html/custom.js
  23. +6
    -6
      code/html/index.html

+ 6
- 2
code/espurna/config/defaults.h View File

@ -556,9 +556,13 @@
// General // General
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Default hostname will be ESPURNA-XXXXXX, where XXXXXX is last 3 octets of chipID
// Device name (DNS, SoftAP SSID, ALEXA etc.)
// If empty, default will be ESPURNA-XXXXXX, where XXXXXX is last 3 octets of chipID
// When set, must be 1..31 characters. See:
// https://github.com/xoseperez/espurna/issues/921
// https://github.com/xoseperez/espurna/issues/1151
#ifndef HOSTNAME #ifndef HOSTNAME
#define HOSTNAME ""
#define HOSTNAME ""
#endif #endif
// Relay providers // Relay providers


+ 4
- 1
code/espurna/config/general.h View File

@ -9,8 +9,11 @@
#define DEVICE_NAME MANUFACTURER "_" DEVICE // Concatenate both to get a unique device name #define DEVICE_NAME MANUFACTURER "_" DEVICE // Concatenate both to get a unique device name
// When defined, ADMIN_PASS must be 8..63 printable ASCII characters. See:
// https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Target_users_(authentication_key_distribution)
// https://github.com/xoseperez/espurna/issues/1151
#ifndef ADMIN_PASS #ifndef ADMIN_PASS
#define ADMIN_PASS "fibonacci" // Default password (WEB, OTA, WIFI)
#define ADMIN_PASS "fibonacci" // Default password (WEB, OTA, WIFI SoftAP)
#endif #endif
#ifndef USE_PASSWORD #ifndef USE_PASSWORD


+ 3
- 0
code/espurna/config/prototypes.h View File

@ -31,6 +31,9 @@ extern "C" {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void debugSend(const char * format, ...); void debugSend(const char * format, ...);
void debugSend_P(PGM_P format, ...); void debugSend_P(PGM_P format, ...);
extern "C" {
void custom_crash_callback(struct rst_info*, uint32_t, uint32_t);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Domoticz // Domoticz


BIN
code/espurna/data/index.all.html.gz View File


BIN
code/espurna/data/index.light.html.gz View File


BIN
code/espurna/data/index.rfbridge.html.gz View File


BIN
code/espurna/data/index.rfm69.html.gz View File


BIN
code/espurna/data/index.sensor.html.gz View File


BIN
code/espurna/data/index.small.html.gz View File


+ 1
- 1
code/espurna/ota.ino View File

@ -16,7 +16,7 @@ void _otaConfigure() {
ArduinoOTA.setPort(OTA_PORT); ArduinoOTA.setPort(OTA_PORT);
ArduinoOTA.setHostname(getSetting("hostname").c_str()); ArduinoOTA.setHostname(getSetting("hostname").c_str());
#if USE_PASSWORD #if USE_PASSWORD
ArduinoOTA.setPassword(getSetting("adminPass", ADMIN_PASS).c_str());
ArduinoOTA.setPassword(getAdminPass().c_str());
#endif #endif
} }


+ 2262
- 2262
code/espurna/static/index.all.html.gz.h
File diff suppressed because it is too large
View File


+ 2210
- 2210
code/espurna/static/index.light.html.gz.h
File diff suppressed because it is too large
View File


+ 1858
- 1858
code/espurna/static/index.rfbridge.html.gz.h
File diff suppressed because it is too large
View File


+ 3224
- 3224
code/espurna/static/index.rfm69.html.gz.h
File diff suppressed because it is too large
View File


+ 1879
- 1879
code/espurna/static/index.sensor.html.gz.h
File diff suppressed because it is too large
View File


+ 1844
- 1844
code/espurna/static/index.small.html.gz.h
File diff suppressed because it is too large
View File


+ 28
- 2
code/espurna/telnet.ino View File

@ -14,6 +14,7 @@ Parts of the code have been borrowed from Thomas Sarlandie's NetServer
AsyncServer * _telnetServer; AsyncServer * _telnetServer;
AsyncClient * _telnetClients[TELNET_MAX_CLIENTS]; AsyncClient * _telnetClients[TELNET_MAX_CLIENTS];
bool _authenticated[TELNET_MAX_CLIENTS];
bool _telnetFirst = true; bool _telnetFirst = true;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -51,11 +52,20 @@ bool _telnetWrite(unsigned char clientId, void *data, size_t len) {
unsigned char _telnetWrite(void *data, size_t len) { unsigned char _telnetWrite(void *data, size_t len) {
unsigned char count = 0; unsigned char count = 0;
for (unsigned char i = 0; i < TELNET_MAX_CLIENTS; i++) { for (unsigned char i = 0; i < TELNET_MAX_CLIENTS; i++) {
if (_telnetWrite(i, data, len)) ++count;
// Do not send broadcast messages to unauthenticated clients
if (_authenticated[i]) {
if (_telnetWrite(i, data, len)) ++count;
}
} }
return count; return count;
} }
bool _telnetWrite(unsigned char clientId, const char * message) {
_telnetWrite(clientId, (void *) message, strlen(message));
}
void _telnetData(unsigned char clientId, void *data, size_t len) { void _telnetData(unsigned char clientId, void *data, size_t len) {
// Skip first message since it's always garbage // Skip first message since it's always garbage
@ -80,7 +90,20 @@ void _telnetData(unsigned char clientId, void *data, size_t len) {
return; return;
} }
// Inject into Embedis stream
// Password
if (!_authenticated[clientId]) {
String password = getAdminPass();
if (strncmp(p, password.c_str(), password.length()) == 0) {
DEBUG_MSG_P(PSTR("[TELNET] Client #%d authenticated\n"), clientId);
_telnetWrite(clientId, "Welcome!\n");
_authenticated[clientId] = true;
} else {
_telnetWrite(clientId, "Password: ");
}
return;
}
// Inject command
settingsInject(data, len); settingsInject(data, len);
} }
@ -109,6 +132,7 @@ void _telnetNewClient(AsyncClient *client) {
} }
for (unsigned char i = 0; i < TELNET_MAX_CLIENTS; i++) { for (unsigned char i = 0; i < TELNET_MAX_CLIENTS; i++) {
if (!_telnetClients[i] || !_telnetClients[i]->connected()) { if (!_telnetClients[i] || !_telnetClients[i]->connected()) {
_telnetClients[i] = client; _telnetClients[i] = client;
@ -144,6 +168,8 @@ void _telnetNewClient(AsyncClient *client) {
#endif #endif
_telnetFirst = true; _telnetFirst = true;
_authenticated[i] = false;
_telnetWrite(i, "Password: ");
wifiReconnectCheck(); wifiReconnectCheck();
return; return;


+ 4
- 0
code/espurna/utils.ino View File

@ -33,6 +33,10 @@ String getBoardName() {
return getSetting("boardName", DEVICE_NAME); return getSetting("boardName", DEVICE_NAME);
} }
String getAdminPass() {
return getSetting("adminPass", ADMIN_PASS);
}
String getCoreVersion() { String getCoreVersion() {
String version = ESP.getCoreVersion(); String version = ESP.getCoreVersion();
#ifdef ARDUINO_ESP8266_RELEASE #ifdef ARDUINO_ESP8266_RELEASE


+ 2
- 2
code/espurna/web.ino View File

@ -347,7 +347,7 @@ void _onRequest(AsyncWebServerRequest *request){
bool webAuthenticate(AsyncWebServerRequest *request) { bool webAuthenticate(AsyncWebServerRequest *request) {
#if USE_PASSWORD #if USE_PASSWORD
String password = getSetting("adminPass", ADMIN_PASS);
String password = getAdminPass();
char httpPassword[password.length() + 1]; char httpPassword[password.length() + 1];
password.toCharArray(httpPassword, password.length() + 1); password.toCharArray(httpPassword, password.length() + 1);
return request->authenticate(WEB_USERNAME, httpPassword); return request->authenticate(WEB_USERNAME, httpPassword);
@ -422,7 +422,7 @@ void webSetup() {
#else #else
_server->begin(); _server->begin();
#endif #endif
DEBUG_MSG_P(PSTR("[WEBSERVER] Webserver running on port %u\n"), port); DEBUG_MSG_P(PSTR("[WEBSERVER] Webserver running on port %u\n"), port);
} }


+ 2
- 2
code/espurna/wifi.ino View File

@ -34,7 +34,7 @@ void _wifiConfigure() {
jw.setHostname(getSetting("hostname").c_str()); jw.setHostname(getSetting("hostname").c_str());
#if USE_PASSWORD #if USE_PASSWORD
jw.setSoftAP(getSetting("hostname").c_str(), getSetting("adminPass", ADMIN_PASS).c_str());
jw.setSoftAP(getSetting("hostname").c_str(), getAdminPass().c_str());
#else #else
jw.setSoftAP(getSetting("hostname").c_str()); jw.setSoftAP(getSetting("hostname").c_str());
#endif #endif
@ -489,7 +489,7 @@ void wifiDebug(WiFiMode_t modes) {
if (((modes & WIFI_AP) > 0) && ((WiFi.getMode() & WIFI_AP) > 0)) { if (((modes & WIFI_AP) > 0) && ((WiFi.getMode() & WIFI_AP) > 0)) {
DEBUG_MSG_P(PSTR("[WIFI] -------------------------------------- MODE AP\n")); DEBUG_MSG_P(PSTR("[WIFI] -------------------------------------- MODE AP\n"));
DEBUG_MSG_P(PSTR("[WIFI] SSID %s\n"), getSetting("hostname").c_str()); DEBUG_MSG_P(PSTR("[WIFI] SSID %s\n"), getSetting("hostname").c_str());
DEBUG_MSG_P(PSTR("[WIFI] PASS %s\n"), getSetting("adminPass", ADMIN_PASS).c_str());
DEBUG_MSG_P(PSTR("[WIFI] PASS %s\n"), getAdminPass().c_str());
DEBUG_MSG_P(PSTR("[WIFI] IP %s\n"), WiFi.softAPIP().toString().c_str()); DEBUG_MSG_P(PSTR("[WIFI] IP %s\n"), WiFi.softAPIP().toString().c_str());
DEBUG_MSG_P(PSTR("[WIFI] MAC %s\n"), WiFi.softAPmacAddress().c_str()); DEBUG_MSG_P(PSTR("[WIFI] MAC %s\n"), WiFi.softAPmacAddress().c_str());
footer = true; footer = true;


+ 1
- 2
code/espurna/ws.ino View File

@ -302,8 +302,7 @@ bool _wsOnReceive(const char * key, JsonVariant& value) {
void _wsOnStart(JsonObject& root) { void _wsOnStart(JsonObject& root) {
#if USE_PASSWORD && WEB_FORCE_PASS_CHANGE #if USE_PASSWORD && WEB_FORCE_PASS_CHANGE
String adminPass = getSetting("adminPass", ADMIN_PASS);
bool changePassword = adminPass.equals(ADMIN_PASS);
bool changePassword = getAdminPass().equals(ADMIN_PASS);
#else #else
bool changePassword = false; bool changePassword = false;
#endif #endif


+ 9
- 5
code/html/custom.js View File

@ -150,13 +150,17 @@ function validateForm(form) {
// http://www.the-art-of-web.com/javascript/validate-password/ // http://www.the-art-of-web.com/javascript/validate-password/
// at least one lowercase and one uppercase letter or number // at least one lowercase and one uppercase letter or number
// at least five characters (letters, numbers or special characters)
var re_password = /^(?=.*[A-Z\d])(?=.*[a-z])[\w~!@#$%^&*\(\)<>,.\?;:{}\[\]\\|]{5,}$/;
// at least eight characters (letters, numbers or special characters)
// MUST be 8..63 printable ASCII characters. See:
// https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Target_users_(authentication_key_distribution)
// https://github.com/xoseperez/espurna/issues/1151
var re_password = /^(?=.*[A-Z\d])(?=.*[a-z])[\w~!@#$%^&*\(\)<>,.\?;:{}\[\]\\|]{8,63}$/;
// password // password
var adminPass1 = $("input[name='adminPass']", form).first().val(); var adminPass1 = $("input[name='adminPass']", form).first().val();
if (adminPass1.length > 0 && !re_password.test(adminPass1)) { if (adminPass1.length > 0 && !re_password.test(adminPass1)) {
alert("The password you have entered is not valid, it must have at least 5 characters, 1 lowercase and 1 uppercase or number!");
alert("The password you have entered is not valid, it must be 8..63 characters and have at least 1 lowercase and 1 uppercase / number!");
return false; return false;
} }
@ -173,9 +177,9 @@ function validateForm(form) {
// No other symbols, punctuation characters, or blank spaces are permitted. // No other symbols, punctuation characters, or blank spaces are permitted.
// Negative lookbehind does not work in Javascript // Negative lookbehind does not work in Javascript
// var re_hostname = new RegExp('^(?!-)[A-Za-z0-9-]{1,32}(?<!-)$');
// var re_hostname = new RegExp('^(?!-)[A-Za-z0-9-]{1,31}(?<!-)$');
var re_hostname = new RegExp('^(?!-)[A-Za-z0-9-]{0,31}[A-Za-z0-9]$');
var re_hostname = new RegExp('^(?!-)[A-Za-z0-9-]{0,30}[A-Za-z0-9]$');
var hostname = $("input[name='hostname']", form); var hostname = $("input[name='hostname']", form);
var hasChanged = hostname.attr("hasChanged") || 0; var hasChanged = hostname.attr("hasChanged") || 0;


+ 6
- 6
code/html/index.html View File

@ -43,11 +43,11 @@
<div class="pure-g"> <div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Admin password</label> <label class="pure-u-1 pure-u-lg-1-4">Admin password</label>
<input name="adminPass" class="pure-u-1 pure-u-lg-3-4" type="password" tabindex="1" autocomplete="false" />
<input name="adminPass" class="pure-u-1 pure-u-lg-3-4" maxlength="63" type="password" tabindex="1" autocomplete="false" />
<div class="pure-u-0 pure-u-lg-1-4"></div> <div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint"> <div class="pure-u-1 pure-u-lg-3-4 hint">
The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).<br /> The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).<br />
It must have at least <strong>five characters</strong> (numbers and letters and any of these special characters: _,.;:~!?@#$%^&amp;*&lt;&gt;\|(){}[]) and at least <strong>one lowercase</strong> and <strong>one uppercase</strong> or <strong>one number</strong>.</div>
It must be <strong>8..63 characters</strong> (numbers and letters and any of these special characters: _,.;:~!?@#$%^&amp;*&lt;&gt;\|(){}[]) and have at least <strong>one lowercase</strong> and <strong>one uppercase</strong> or <strong>one number</strong>.</div>
</div> </div>
<div class="pure-g"> <div class="pure-g">
@ -323,7 +323,7 @@
<div class="pure-g"> <div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Hostname</label> <label class="pure-u-1 pure-u-lg-1-4">Hostname</label>
<input name="hostname" class="pure-u-1 pure-u-lg-1-4" maxlength="32" type="text" action="reboot" tabindex="1" />
<input name="hostname" class="pure-u-1 pure-u-lg-1-4" maxlength="31" type="text" action="reboot" tabindex="1" />
<div class="pure-u-0 pure-u-lg-1-2"></div> <div class="pure-u-0 pure-u-lg-1-2"></div>
<div class="pure-u-0 pure-u-lg-1-4"></div> <div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint"> <div class="pure-u-1 pure-u-lg-3-4 hint">
@ -522,16 +522,16 @@
<div class="pure-g"> <div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Admin password</label> <label class="pure-u-1 pure-u-lg-1-4">Admin password</label>
<input name="adminPass" class="pure-u-1 pure-u-lg-3-4" type="password" action="reboot" tabindex="11" autocomplete="false" />
<input name="adminPass" class="pure-u-1 pure-u-lg-3-4" maxlength="63" type="password" action="reboot" tabindex="11" autocomplete="false" />
<div class="pure-u-0 pure-u-lg-1-4"></div> <div class="pure-u-0 pure-u-lg-1-4"></div>
<div class="pure-u-1 pure-u-lg-3-4 hint"> <div class="pure-u-1 pure-u-lg-3-4 hint">
The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).<br /> The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).<br />
It must have at least <strong>five characters</strong> (numbers and letters and any of these special characters: _,.;:~!?@#$%^&amp;*&lt;&gt;\|(){}[]) and at least <strong>one lowercase</strong> and <strong>one uppercase</strong> or <strong>one number</strong>.</div>
It must be <strong>8..63 characters</strong> (numbers and letters and any of these special characters: _,.;:~!?@#$%^&amp;*&lt;&gt;\|(){}[]) and have at least <strong>one lowercase</strong> and <strong>one uppercase</strong> or <strong>one number</strong>.</div>
</div> </div>
<div class="pure-g"> <div class="pure-g">
<label class="pure-u-1 pure-u-lg-1-4">Repeat password</label> <label class="pure-u-1 pure-u-lg-1-4">Repeat password</label>
<input name="adminPass" class="pure-u-1 pure-u-lg-3-4" type="password" action="reboot" tabindex="12" autocomplete="false" />
<input name="adminPass" class="pure-u-1 pure-u-lg-3-4" maxlength="63" type="password" action="reboot" tabindex="12" autocomplete="false" />
</div> </div>
<div class="pure-g"> <div class="pure-g">


Loading…
Cancel
Save