diff --git a/tasmota/settings.h b/tasmota/settings.h index 075759b716b3..7a9a50367de4 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -436,7 +436,7 @@ typedef union { } DisplayOptions; const uint32_t settings_text_size = 699; // Settings->text_pool[size] = Settings->display_model (2D2) - Settings->text_pool (017) -const uint8_t MAX_TUYA_FUNCTIONS = 16; +const uint8_t MAX_TUYA_FUNCTIONS = 1; typedef struct { uint16_t cfg_holder; // 000 v6 header @@ -689,7 +689,6 @@ typedef struct { uint16_t syslog_port; // ECA uint8_t syslog_level; // ECC uint8_t webserver; // ECD - uint8_t weblog_level; // ECE uint8_t mqtt_fingerprint[2][20]; // ECF uint8_t ex_adc_param_type; // EF7 Free since 9.0.0.1 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 5569f2debf37..2820c6ba1d86 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -877,8 +877,6 @@ void SettingsDefaultSet2(void) { flag3.gui_hostname_ip |= GUI_SHOW_HOSTNAME; flag3.mdns_enabled |= MDNS_ENABLED; Settings->webserver = WEB_SERVER; - Settings->weblog_level = WEB_LOG_LEVEL; - SettingsUpdateText(SET_WEBPWD, PSTR(WEB_PASSWORD)); SettingsUpdateText(SET_CORS, PSTR(CORS_DOMAIN)); // Button diff --git a/tasmota/support.ino b/tasmota/support.ino index 16852a5657bf..5c513a232b16 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -2360,8 +2360,7 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa if (!TasmotaGlobal.log_buffer) { return; } // Leave now if there is no buffer available - uint32_t highest_loglevel = Settings->weblog_level; - if (Settings->mqttlog_level > highest_loglevel) { highest_loglevel = Settings->mqttlog_level; } + uint32_t highest_loglevel = Settings->mqttlog_level; if (TasmotaGlobal.syslog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.syslog_level; } if (TasmotaGlobal.templog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.templog_level; } if (TasmotaGlobal.uptime < 3) { highest_loglevel = LOG_LEVEL_DEBUG_MORE; } // Log all before setup correct log level diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index 0fa0370d664b..8c437911ac76 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -525,10 +525,10 @@ void CmndStatus(void) } if ((0 == payload) || (3 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_MQTTLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\",\"%08X\",\"%08X\"]}}"), - Settings->seriallog_level, Settings->weblog_level, Settings->mqttlog_level, Settings->syslog_level, + Settings->seriallog_level, Settings->mqttlog_level, Settings->syslog_level, SettingsText(SET_SYSLOG_HOST), Settings->syslog_port, EscapeJSONString(SettingsText(SET_STASSID1)).c_str(), EscapeJSONString(SettingsText(SET_STASSID2)).c_str(), Settings->tele_period, Settings->flag2.data, Settings->flag.data, ToHex_P((unsigned char*)Settings->param, PARAM8_SIZE, stemp2, sizeof(stemp2)), Settings->flag3.data, Settings->flag4.data, Settings->flag5.data); diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 80d41aef8ccf..aefcb4ff5357 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -1315,7 +1315,10 @@ void Every250mSeconds(void) if (Settings->webserver) { #ifdef ESP8266 - if (!WifiIsInManagerMode()) { StartWebserver(Settings->webserver, WiFi.localIP()); } + if (!WifiIsInManagerMode()) { + StartWebserver(Settings->webserver, WiFi.localIP()); + StartWebserverSecure(); + } #endif // ESP8266 #ifdef ESP32 #ifdef USE_ETHERNET @@ -1328,6 +1331,7 @@ void Every250mSeconds(void) MdnsAddServiceHttp(); } else { StopWebserver(); + StopWebserverSecure(); } #ifdef USE_EMULATION if (Settings->flag2.emulation) { UdpConnect(); } @@ -1378,9 +1382,6 @@ void ArduinoOTAInit(void) { ArduinoOTA.setPort(8266); ArduinoOTA.setHostname(NetworkHostname()); - if (strlen(SettingsText(SET_WEBPWD))) { - ArduinoOTA.setPassword(SettingsText(SET_WEBPWD)); - } ArduinoOTA.onStart([]() { diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 1d2a92d547cc..8c22c25c1972 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -64,10 +64,10 @@ const uint8_t MAX_PWMS = 5; // Max number of PWM channels const uint8_t MAX_COUNTERS = 4; // Max number of counter sensors const uint8_t MAX_TIMERS = 16; // Max number of Timers const uint8_t MAX_PULSETIMERS = 8; // Max number of supported pulse timers -const uint8_t MAX_DOMOTICZ_IDX = 4; // Max number of Domoticz device, key and switch indices -const uint8_t MAX_DOMOTICZ_SNS_IDX = 12; // Max number of Domoticz sensors indices -const uint8_t MAX_KNX_GA = 10; // Max number of KNX Group Addresses to read that can be set -const uint8_t MAX_KNX_CB = 10; // Max number of KNX Group Addresses to write that can be set +const uint8_t MAX_DOMOTICZ_IDX = 1; // Max number of Domoticz device, key and switch indices +const uint8_t MAX_DOMOTICZ_SNS_IDX = 1; // Max number of Domoticz sensors indices +const uint8_t MAX_KNX_GA = 1; // Max number of KNX Group Addresses to read that can be set +const uint8_t MAX_KNX_CB = 1; // Max number of KNX Group Addresses to write that can be set const uint8_t MAX_XNRG_DRIVERS = 32; // Max number of allowed energy drivers const uint8_t MAX_XDSP_DRIVERS = 32; // Max number of allowed display drivers const uint8_t MAX_XDRV_DRIVERS = 96; // Max number of allowed driver drivers @@ -78,7 +78,7 @@ const uint8_t MAX_SHUTTER_RELAYS = 8; // Max number of shutter relays const uint8_t MAX_SHUTTER_KEYS = 4; // Max number of shutter keys or buttons const uint8_t MAX_PCF8574 = 4; // Max number of PCF8574 devices const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters -const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules +const uint16_t MAX_RULE_SIZE = 1; // Max number of characters in rules const uint16_t VL53L0X_MAX_SENSORS = 8; // Max number of VL53L0X sensors #ifdef ESP32 @@ -123,6 +123,8 @@ const char WIFI_HOSTNAME[] = "ZIGBANG"; // Expands to - #include +#include +#include const char HTTP_SCRIPT_ROOT2[] PROGMEM = "var rfsh=1,ft;" @@ -183,63 +185,6 @@ const char HTTP_SCRIPT_RELOAD_TIME[] PROGMEM = #include "./html_uncompressed/HTTP_SCRIPT_CONSOL.h" #endif -const char HTTP_MODULE_TEMPLATE_REPLACE_INDEX[] PROGMEM = - "}2%d'>%s (%d)}3"; // }2 and }3 are used in below os.replace -const char HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX[] PROGMEM = - "}2%d'>%s}3"; // }2 and }3 are used in below os.replace - -#ifdef USE_UNISHOX_COMPRESSION - #include "./html_compressed/HTTP_SCRIPT_MODULE_TEMPLATE.h" - #include "./html_compressed/HTTP_SCRIPT_TEMPLATE.h" -#else - #include "./html_uncompressed/HTTP_SCRIPT_MODULE_TEMPLATE.h" - #include "./html_uncompressed/HTTP_SCRIPT_TEMPLATE.h" -#endif - -#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32C3 -const char HTTP_SCRIPT_TEMPLATE2[] PROGMEM = - "for(i=0;i<" STR(MAX_USER_PINS) ";i++){" - "sk(g[i],i);" // Set GPIO - "}"; -#else // Now ESP32 and ESP8266 -const char HTTP_SCRIPT_TEMPLATE2[] PROGMEM = - "j=0;" - "for(i=0;i<" STR(MAX_USER_PINS) ";i++){" // Supports 13 GPIOs - "if(6==i){j=9;}" - "if(8==i){j=12;}" - "sk(g[i],j);" // Set GPIO - "j++;" - "}"; -#endif -const char HTTP_SCRIPT_TEMPLATE3[] PROGMEM = - "\";" - "sk(g[13]," STR(ADC0_PIN) ");"; // Set ADC0 - -const char HTTP_SCRIPT_TEMPLATE4[] PROGMEM = - "g=o.shift();" // FLAG - "for(i=0;i<" STR(GPIO_FLAG_USED) ";i++){" - "p=(g>>i)&1;" - "eb('c'+i).checked=p;" // Set FLAG checkboxes - "}" - "if(" STR(USER_MODULE) "==c){" - "g=o.shift();" - "eb('g99').value=g;" // Set BASE for initial select - "}" - "}" - "function st(t){" - "c=t;" // Needed for initial BASE select - "var a='tp?t='+t;" - "ld(a,x1);" // ?t related to WebGetArg("t", stemp, sizeof(stemp)); - "}" - "function sl(){" - "os=\""; // }2'0'>Sonoff Basic (1)}3... -const char HTTP_SCRIPT_TEMPLATE5[] PROGMEM = - "\";" - "sk(" STR(WEMOS_MODULE) ",99);" // 17 = WEMOS - "st(" STR(USER_MODULE) ");" - "}" - "wl(sl);"; - const char HTTP_SCRIPT_INFO_BEGIN[] PROGMEM = "function i(){" "var s,o=\""; @@ -328,21 +273,6 @@ const char HTTP_FORM_LOGIN[] PROGMEM = "" ""; -const char HTTP_FORM_TEMPLATE[] PROGMEM = - "
 " D_TEMPLATE_PARAMETERS " " - "
"; -const char HTTP_FORM_TEMPLATE_FLAG[] PROGMEM = - "

" // Keep close so do not use
- "
 " D_TEMPLATE_FLAGS " 

" -// "
" - "

"; - -const char HTTP_FORM_MODULE[] PROGMEM = - "
 " D_MODULE_PARAMETERS " " - "" - "

" D_MODULE_TYPE " (%s)

" - "
"; - const char HTTP_FORM_WIFI_PART1[] PROGMEM = "
 " D_WIFI_PARAMETERS " " "" @@ -356,30 +286,6 @@ const char HTTP_FORM_WIFI_PART2[] PROGMEM = "

" D_HOSTNAME " (%s)

" "

" D_CORS_DOMAIN "

"; -const char HTTP_FORM_LOG1[] PROGMEM = - "
 " D_LOGGING_PARAMETERS " " - ""; -const char HTTP_FORM_LOG2[] PROGMEM = - "

" D_SYSLOG_HOST " (" SYS_LOG_HOST ")

" - "

" D_SYSLOG_PORT " (" STR(SYS_LOG_PORT) ")

" - "

" D_TELEMETRY_PERIOD " (" STR(TELE_PERIOD) ")

"; - -const char HTTP_FORM_OTHER[] PROGMEM = - "
 " D_OTHER_PARAMETERS " " - "" - "

" - "
 " D_TEMPLATE " " - "

" // We need ' apostrophe here as the template contains " quotation mark - "

" - "
" - "
" - "

" - "
" - "
" - "
" - "

" - "
"; - const char HTTP_FORM_END[] PROGMEM = "
" "" @@ -427,27 +333,21 @@ const char HTTP_DEVICE_STATE[] PROGMEM = "
"); - WSContentSend_P("
"); + WSContentSend_P(PSTR("
")); + WSContentSend_P(PSTR("
")); WSContentSend_P(PSTR("
")); @@ -1127,6 +993,8 @@ void HandleRoot(void) #endif // Not FIRMWARE_MINIMAL if (HTTP_ADMIN == Web.state) { + if (!Web.state_login) { WSContentSpaceButton(BUTTON_COGNITO_LOGIN); } + else { WSContentSpaceButton(BUTTON_COGNITO_LOGOUT); } WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentButton(BUTTON_INFORMATION); WSContentButton(BUTTON_RESTART); @@ -1136,11 +1004,6 @@ void HandleRoot(void) bool HandleRootStatusRefresh(void) { - if (!WebAuthenticate()) { - Webserver->requestAuthentication(); - return true; - } - if (!Webserver->hasArg("m")) { // Status refresh requested return false; } @@ -1154,7 +1017,7 @@ bool HandleRootStatusRefresh(void) WSContentSend_P(PSTR("

")); WSContentSend_P(PSTR("\n\n")); // Prep for SSE if (!TasmotaGlobal.mqtt_connected) { - WSContentSend_P("
{loader}
"); + WSContentSend_P(PSTR("
{loader}
")); } WSContentEnd(); @@ -1183,8 +1046,6 @@ int32_t IsShutterWebButton(uint32_t idx) { void HandleConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURATION)); WSContentStart_P(PSTR(D_CONFIGURATION)); @@ -1201,303 +1062,6 @@ void HandleConfiguration(void) /*-------------------------------------------------------------------------------------------*/ -void WSContentSendNiceLists(uint32_t option) { - char stemp[30]; // Template number and Sensor name - for (uint32_t i = 0; i < nitems(kGpioNiceList); i++) { // GPIO: }2'0'>None (0)}3}2'17'>Button1 (17)}3... - if (option && (1 == i)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), PSTR(D_SENSOR_USER)); // }2'255'>User}3 - } - uint32_t ridx = pgm_read_word(kGpioNiceList + i) & 0xFFE0; - uint32_t midx = BGPIO(ridx); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames)); - } - WSContentSend_P(PSTR("\";")); - - WSContentSend_P(PSTR("hs=[")); - uint32_t midx; - bool first_done = false; - for (uint32_t i = 0; i < nitems(kGpioNiceList); i++) { // hs=[36,68,100,132,168,200,232,264,292,324,356,388,421,453]; - midx = pgm_read_word(kGpioNiceList + i); - if (midx & 0x001F) { - if (first_done) { WSContentSend_P(PSTR(",")); } - WSContentSend_P(PSTR("%d"), midx); - first_done = true; - } - } -#ifdef ESP8266 -#ifdef USE_ADC - for (uint32_t i = 0; i < nitems(kAdcNiceList); i++) { // hs=[36,68,100,132,168,200,232,264,292,324,356,388,421,453]; - midx = pgm_read_word(kAdcNiceList + i); - if (midx & 0x001F) { - if (first_done) { WSContentSend_P(PSTR(",")); } - WSContentSend_P(PSTR("%d"), midx); - first_done = true; - } - } -#endif // USE_ADC -#endif // ESP8266 - WSContentSend_P(PSTR("];")); -} - -#ifdef ESP8266 -#ifdef USE_ADC -void WSContentSendAdcNiceList(uint32_t option) { - char stemp[30]; // Template number and Sensor name - WSContentSend_P(PSTR("os=\"")); - for (uint32_t i = 0; i < nitems(kAdcNiceList); i++) { // GPIO: }2'0'>None}3}2'17'>Analog}3... - if (option && (1 == i)) { - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, AGPIO(GPIO_USER), PSTR(D_SENSOR_USER)); // }2'15'>User}3 - } - uint32_t ridx = pgm_read_word(kAdcNiceList + i) & 0xFFE0; - uint32_t midx = BGPIO(ridx); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_NO_INDEX, ridx, GetTextIndexed(stemp, sizeof(stemp), midx, kSensorNames)); - } -} -#endif // USE_ADC -#endif // ESP8266 - -/*-------------------------------------------------------------------------------------------*/ - -void HandleTemplateConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - if (Webserver->hasArg(F("save"))) { - TemplateSaveSettings(); - WebRestart(1); - return; - } - - char stemp[30]; // Template number and Sensor name - - WebGetArg(PSTR("t"), stemp, sizeof(stemp)); // 0 - 69 Template number - if (strlen(stemp)) { - uint32_t module = atoi(stemp); - uint32_t module_save = Settings->module; - Settings->module = module; - myio template_gp; - TemplateGpios(&template_gp); - gpio_flag flag = ModuleFlag(); - Settings->module = module_save; - - WSContentBegin(200, CT_PLAIN); - WSContentSend_P(PSTR("%s}1"), AnyModuleName(module).c_str()); // NAME: Generic - for (uint32_t i = 0; i < nitems(template_gp.io); i++) { // 17,148,29,149,7,255,255,255,138,255,139,255,255 -#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32C3 - // ESP32C3 we always send all GPIOs, Flash are just hidden - WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", template_gp.io[i]); -#else - if (!FlashPin(i)) { - WSContentSend_P(PSTR("%s%d"), (i>0)?",":"", template_gp.io[i]); - } -#endif - } - WSContentSend_P(PSTR("}1%d}1%d"), flag, Settings->user_template_base); // FLAG: 1 BASE: 17 - WSContentEnd(); - return; - } - - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_TEMPLATE)); - - WSContentStart_P(PSTR(D_CONFIGURE_TEMPLATE)); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - - WSContentSend_P(HTTP_SCRIPT_TEMPLATE); - - WSContentSendNiceLists(1); - - WSContentSend_P(HTTP_SCRIPT_TEMPLATE2); - -#ifdef ESP8266 -#ifdef USE_ADC - WSContentSendAdcNiceList(1); - WSContentSend_P(HTTP_SCRIPT_TEMPLATE3); -#endif // USE_ADC -#endif // ESP8266 - - WSContentSend_P(HTTP_SCRIPT_TEMPLATE4); - for (uint32_t i = 0; i < sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" - uint32_t midx = pgm_read_byte(kModuleNiceList + i); - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_INDEX, midx, AnyModuleName(midx).c_str(), midx +1); - } - WSContentSend_P(HTTP_SCRIPT_TEMPLATE5); - - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_TEMPLATE); - WSContentSend_P(HTTP_TABLE100); - WSContentSend_P(PSTR("" D_TEMPLATE_NAME "" - "" D_BASE_TYPE "" - "" - "
")); - WSContentSend_P(HTTP_TABLE100); - for (uint32_t i = 0; i < MAX_GPIO_PIN; i++) { -#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32C3 - // ESP32C3 all gpios are in the template, flash are hidden - bool hidden = FlashPin(i); - WSContentSend_P(PSTR("" D_GPIO "%d"), - hidden ? PSTR(" hidden") : "", - RedPin(i) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? PSTR(" style='width:146px'") : "", i, i); - WSContentSend_P(PSTR(""), i); -#else - if (!FlashPin(i)) { - WSContentSend_P(PSTR("" D_GPIO "%d"), - RedPin(i) ? WebColor(COL_TEXT_WARNING) : WebColor(COL_TEXT), i, (0==i) ? PSTR(" style='width:146px'") : "", i, i); - WSContentSend_P(PSTR(""), i); - } -#endif - } - WSContentSend_P(PSTR("")); - - gpio_flag flag = ModuleFlag(); - if (flag.data) { - WSContentSend_P(HTTP_FORM_TEMPLATE_FLAG); - } - - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -uint16_t WebGetGpioArg(uint32_t i) { - char webindex[5]; // WebGetArg name - snprintf_P(webindex, sizeof(webindex), PSTR("g%d"), i); - char tmp[8]; // WebGetArg numbers only - WebGetArg(webindex, tmp, sizeof(tmp)); // GPIO - uint32_t gpio = (!strlen(tmp)) ? 0 : atoi(tmp); - char webindex2[5]; // WebGetArg name - snprintf_P(webindex2, sizeof(webindex2), PSTR("h%d"), i); - char tmp2[8]; // WebGetArg numbers only - WebGetArg(webindex2, tmp2, sizeof(tmp2)); - uint32_t value2 = (!strlen(tmp2)) ? 0 : atoi(tmp2) -1; - gpio += value2; - return gpio; -} - -void TemplateSaveSettings(void) { - char tmp[TOPSZ]; // WebGetArg NAME and GPIO/BASE/FLAG byte value - char command[300]; // Template command string - - WebGetArg(PSTR("s1"), tmp, sizeof(tmp)); // NAME - snprintf_P(command, sizeof(command), PSTR(D_CMND_TEMPLATE " {\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), tmp); - - uint32_t j = 0; - for (uint32_t i = 0; i < nitems(Settings->user_template.gp.io); i++) { -#if defined(ESP32) && CONFIG_IDF_TARGET_ESP32C3 - snprintf_P(command, sizeof(command), PSTR("%s%s%d"), command, (i>0)?",":"", WebGetGpioArg(i)); -#else - if (6 == i) { j = 9; } - if (8 == i) { j = 12; } - snprintf_P(command, sizeof(command), PSTR("%s%s%d"), command, (i>0)?",":"", WebGetGpioArg(j)); - j++; -#endif - } - - uint32_t flag = 0; - char webindex[5]; // WebGetArg name - for (uint32_t i = 0; i < GPIO_FLAG_USED; i++) { - snprintf_P(webindex, sizeof(webindex), PSTR("c%d"), i); - uint32_t state = Webserver->hasArg(webindex) << i; // FLAG - flag += state; - } - WebGetArg(PSTR("g99"), tmp, sizeof(tmp)); // BASE - uint32_t base = atoi(tmp) +1; - - snprintf_P(command, sizeof(command), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), command, flag, base); - ExecuteWebCommand(command); -} - -/*-------------------------------------------------------------------------------------------*/ - -void HandleModuleConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - if (Webserver->hasArg(F("save"))) { - ModuleSaveSettings(); - WebRestart(1); - return; - } - - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_MODULE)); - - char stemp[30]; // Sensor name - uint32_t midx; - myio template_gp; - TemplateGpios(&template_gp); - - WSContentStart_P(PSTR(D_CONFIGURE_MODULE)); - WSContentSend_P(HTTP_SCRIPT_MODULE_TEMPLATE); - - WSContentSend_P(PSTR("function sl(){os=\"")); - uint32_t vidx = 0; - for (uint32_t i = 0; i <= sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" - if (0 == i) { - midx = USER_MODULE; - vidx = 0; - } else { - midx = pgm_read_byte(kModuleNiceList + i -1); - vidx = midx +1; - } - WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE_INDEX, midx, AnyModuleName(midx).c_str(), vidx); - } - WSContentSend_P(PSTR("\";sk(%d,99);os=\""), Settings->module); - - WSContentSendNiceLists(0); - - for (uint32_t i = 0; i < nitems(template_gp.io); i++) { - if (ValidGPIO(i, template_gp.io[i])) { - WSContentSend_P(PSTR("sk(%d,%d);"), TasmotaGlobal.my_module.io[i], i); // g0 - g17 - } - } - -#ifdef ESP8266 -#ifdef USE_ADC - WSContentSendAdcNiceList(0); - WSContentSend_P(PSTR("\";sk(%d," STR(ADC0_PIN) ");"), Settings->my_gp.io[(sizeof(myio) / 2) -1]); -#endif // USE_ADC -#endif // ESP8266 - - WSContentSend_P(PSTR("}wl(sl);")); - - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_MODULE, AnyModuleName(MODULE).c_str()); - for (uint32_t i = 0; i < nitems(template_gp.io); i++) { - if (ValidGPIO(i, template_gp.io[i])) { - snprintf_P(stemp, 3, PINS_WEMOS +i*2); - WSContentSend_P(PSTR("%s " D_GPIO "%d"), - (WEMOS==TasmotaGlobal.module_type)?stemp:"", i, i, i); - WSContentSend_P(PSTR(""), i); - } - } - WSContentSend_P(PSTR("")); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void ModuleSaveSettings(void) { - char tmp[8]; // WebGetArg numbers only - WebGetArg(PSTR("g99"), tmp, sizeof(tmp)); // Module - uint32_t new_module = (!strlen(tmp)) ? MODULE : atoi(tmp); - Settings->last_module = Settings->module; - Settings->module = new_module; - SetModuleType(); - myio template_gp; - TemplateGpios(&template_gp); - for (uint32_t i = 0; i < nitems(template_gp.io); i++) { - if (Settings->last_module != new_module) { - Settings->my_gp.io[i] = GPIO_NONE; - } else { - if (ValidGPIO(i, template_gp.io[i])) { - Settings->my_gp.io[i] = WebGetGpioArg(i); // Gpio - } - } - } - char command[32]; - snprintf_P(command, sizeof(command), PSTR(D_CMND_BACKLOG "0 " D_CMND_MODULE ";" D_CMND_GPIO)); - ExecuteWebCommand(command); -} - -/*-------------------------------------------------------------------------------------------*/ - const char kUnescapeCode[] = "&><\"\'\\"; const char kEscapeCode[] PROGMEM = "&|>|<|"|'|\"; @@ -1520,8 +1084,6 @@ String HtmlEscape(const String unescaped) { void HandleWifiConfiguration(void) { char tmp[TOPSZ]; // Max length is currently 150 - if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_WIFI)); if (Webserver->hasArg(F("save")) && HTTP_MANAGER_RESET_ONLY != Web.state) { @@ -1770,156 +1332,8 @@ void WifiSaveSettings(void) { /*-------------------------------------------------------------------------------------------*/ -void HandleLoggingConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_LOGGING)); - - if (Webserver->hasArg("save")) { - LoggingSaveSettings(); - HandleConfiguration(); - return; - } - - WSContentStart_P(PSTR(D_CONFIGURE_LOGGING)); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_LOG1); - char stemp1[45]; - char stemp2[32]; - uint8_t dlevel[4] = { LOG_LEVEL_INFO, LOG_LEVEL_INFO, LOG_LEVEL_NONE, LOG_LEVEL_NONE }; - for (uint32_t idx = 0; idx < 4; idx++) { - if ((2==idx) && !Settings->flag.mqtt_enabled) { continue; } // SetOption3 - Enable MQTT - uint32_t llevel = (0==idx)?Settings->seriallog_level:(1==idx)?Settings->weblog_level:(2==idx)?Settings->mqttlog_level:Settings->syslog_level; - WSContentSend_P(PSTR("

%s (%s)

")); - } - WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings->syslog_port, Settings->tele_period); - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void LoggingSaveSettings(void) { - String cmnd = F(D_CMND_BACKLOG "0 "); - cmnd += AddWebCommand(PSTR(D_CMND_SERIALLOG), PSTR("l0"), STR(SERIAL_LOG_LEVEL)); - cmnd += AddWebCommand(PSTR(D_CMND_WEBLOG), PSTR("l1"), STR(WEB_LOG_LEVEL)); - cmnd += AddWebCommand(PSTR(D_CMND_MQTTLOG), PSTR("l2"), STR(MQTT_LOG_LEVEL)); - cmnd += AddWebCommand(PSTR(D_CMND_SYSLOG), PSTR("l3"), STR(SYS_LOG_LEVEL)); - cmnd += AddWebCommand(PSTR(D_CMND_LOGHOST), PSTR("lh"), PSTR("1")); - cmnd += AddWebCommand(PSTR(D_CMND_LOGPORT), PSTR("lp"), PSTR("1")); - cmnd += AddWebCommand(PSTR(D_CMND_TELEPERIOD), PSTR("lt"), PSTR("1")); - ExecuteWebCommand((char*)cmnd.c_str()); -} - -/*-------------------------------------------------------------------------------------------*/ - -void HandleOtherConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_OTHER)); - - if (Webserver->hasArg(F("save"))) { - OtherSaveSettings(); - WebRestart(1); - return; - } - - WSContentStart_P(PSTR(D_CONFIGURE_OTHER)); - WSContentSendStyle(); - - TemplateJson(); -#ifdef MQTT_DATA_STRING - WSContentSend_P(HTTP_FORM_OTHER, TasmotaGlobal.mqtt_data.c_str(), (USER_MODULE == Settings->module) ? PSTR(" checked disabled") : "", -#else - WSContentSend_P(HTTP_FORM_OTHER, TasmotaGlobal.mqtt_data, (USER_MODULE == Settings->module) ? PSTR(" checked disabled") : "", -#endif - (Settings->flag.mqtt_enabled) ? PSTR(" checked") : "", // SetOption3 - Enable MQTT - SettingsText(SET_FRIENDLYNAME1), SettingsText(SET_DEVICENAME)); - - char stemp[32]; - uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present; -#ifdef USE_SONOFF_IFAN - if (IsModuleIfan()) { maxfn = 1; } -#endif // USE_SONOFF_IFAN - for (uint32_t i = 0; i < maxfn; i++) { - snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i +1); - WSContentSend_P(PSTR("" D_FRIENDLY_NAME " %d (" FRIENDLY_NAME "%s)

"), - i +1, - (i) ? stemp : "", - i, - (i) ? stemp : "", - SettingsText(SET_FRIENDLYNAME1 + i)); - } - -#ifdef USE_EMULATION -#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) - WSContentSend_P(PSTR("

 " D_EMULATION " 

")); // Keep close to Friendlynames so do not use
- for (uint32_t i = 0; i < EMUL_MAX; i++) { -#ifndef USE_EMULATION_WEMO - if (i == EMUL_WEMO) { i++; } -#endif -#ifndef USE_EMULATION_HUE - if (i == EMUL_HUE) { i++; } -#endif - if (i < EMUL_MAX) { - WSContentSend_P(PSTR("%s %s
"), // Different id only used for labels - i, i, - (i == Settings->flag2.emulation) ? PSTR(" checked") : "", - GetTextIndexed(stemp, sizeof(stemp), i, kEmulationOptions), - (i == EMUL_NONE) ? "" : (i == EMUL_WEMO) ? PSTR(D_SINGLE_DEVICE) : PSTR(D_MULTI_DEVICE)); - } - } - WSContentSend_P(PSTR("

")); -#endif // USE_EMULATION_WEMO || USE_EMULATION_HUE -#endif // USE_EMULATION - - WSContentSend_P(HTTP_FORM_END); - WSContentSpaceButton(BUTTON_CONFIGURATION); - WSContentStop(); -} - -void OtherSaveSettings(void) { - String cmnd = F(D_CMND_BACKLOG "0 "); - cmnd += AddWebCommand(PSTR(D_CMND_WEBPASSWORD "2"), PSTR("wp"), PSTR("\"")); - cmnd += F(";" D_CMND_SO "3 "); - cmnd += Webserver->hasArg(F("b1")); - cmnd += AddWebCommand(PSTR(D_CMND_DEVICENAME), PSTR("dn"), PSTR("\"")); - char webindex[5]; - char cmnd2[24]; // ";Module 0;Template " - for (uint32_t i = 0; i < MAX_FRIENDLYNAMES; i++) { - snprintf_P(webindex, sizeof(webindex), PSTR("a%d"), i); - snprintf_P(cmnd2, sizeof(cmnd2), PSTR(D_CMND_FN "%d"), i +1); - cmnd += AddWebCommand(cmnd2, webindex, PSTR("\"")); - } - -#ifdef USE_EMULATION -#if defined(USE_EMULATION_WEMO) || defined(USE_EMULATION_HUE) - cmnd += AddWebCommand(PSTR(D_CMND_EMULATION), PSTR("b2"), PSTR("0")); -#endif // USE_EMULATION_WEMO || USE_EMULATION_HUE -#endif // USE_EMULATION - - String tmpl = Webserver->arg(F("t1")); // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255,"CMND":"SO123 1;SO99 0"} - if (tmpl.length() && (tmpl.length() < MQTT_MAX_PACKET_SIZE)) { - snprintf_P(cmnd2, sizeof(cmnd2), PSTR(";%s" D_CMND_TEMPLATE " "), (Webserver->hasArg(F("t2"))) ? PSTR(D_CMND_MODULE " 0;") : ""); - cmnd += cmnd2 + tmpl; - } - ExecuteWebCommand((char*)cmnd.c_str()); -} - -/*-------------------------------------------------------------------------------------------*/ - void HandleBackupConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_BACKUP_CONFIGURATION)); uint32_t config_len = SettingsConfigBackup(); @@ -1942,8 +1356,6 @@ void HandleBackupConfiguration(void) void HandleResetConfiguration(void) { - if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_RESET_CONFIGURATION)); WSContentStart_P(PSTR(D_RESET_CONFIGURATION), !WifiIsInManagerMode()); @@ -1960,13 +1372,11 @@ void HandleResetConfiguration(void) void HandleFactoryResetConfiguration(void) { - if (!HttpCheckPriviledgedAccess(!WifiIsInManagerMode())) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR("공장 초기화 중...")); WSContentStart_P(PSTR("공장 초기화"), !WifiIsInManagerMode()); WSContentSendStyle(); - WSContentSend_P(PSTR("
" D_CONFIGURATION_RESET "
")); + WSContentSend_P(PSTR("
공장 초기화
")); WSContentSend_P(HTTP_MSG_RSTRT); WSContentSpaceButton(BUTTON_MAIN); WSContentStop(); @@ -1978,8 +1388,6 @@ void HandleFactoryResetConfiguration(void) void HandleRestoreConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_RESTORE_CONFIGURATION)); WSContentStart_P(PSTR(D_RESTORE_CONFIGURATION)); @@ -2000,8 +1408,6 @@ void HandleRestoreConfiguration(void) void HandleInformation(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - float freemem = ((float)ESP_getFreeHeap()) / 1024; AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_INFORMATION)); @@ -2135,8 +1541,8 @@ void HandleInformation(void) WSContentSend_PD(PSTR("}1" D_FREE_MEMORY "}2%1_f kB"), &freemem); #endif // ESP32 WSContentSend_P(PSTR("")); - WSContentSend_P("\";s=o.replace(/}1/g,\"\").replace(/}2/g,\"\");eb('hide').innerHTML=s;}wl(hide);"); - WSContentSend_P("
"); + WSContentSend_P(PSTR("\";s=o.replace(/}1/g,\"\").replace(/}2/g,\"\");eb('hide').innerHTML=s;}wl(hide);")); + WSContentSend_P(PSTR("
")); WSContentSend_P(PSTR("")); WSContentSpaceButton(BUTTON_MAIN); @@ -2193,8 +1599,6 @@ uint32_t BUploadWriteBuffer(uint8_t *buf, size_t size) { #endif // USE_WEB_FW_UPGRADE void HandleUpgradeFirmware(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_FIRMWARE_UPGRADE)); WSContentStart_P(PSTR(D_FIRMWARE_UPGRADE)); @@ -2208,8 +1612,6 @@ void HandleUpgradeFirmware(void) { } void HandleUpgradeFirmwareStart(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - char command[TOPSZ + 10]; // OtaUrl AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_UPGRADE_STARTED)); @@ -2235,8 +1637,6 @@ void HandleUpgradeFirmwareStart(void) { } void HandleUploadDone(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - #if defined(USE_ZIGBEE_EZSP) if ((UPL_EFR32 == Web.upload_file_type) && !Web.upload_error && BUpload.ready) { BUpload.ready = false; // Make sure not to follow thru again @@ -2575,25 +1975,8 @@ void HandlePreflightRequest(void) void HandleHttpCommand(void) { - if (!HttpCheckPriviledgedAccess(false)) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_COMMAND)); - if (!WebAuthenticate()) { - // Prefer authorization via HTTP header (Basic auth), if it fails, use legacy method via GET parameters - char tmp1[33]; - WebGetArg(PSTR("user"), tmp1, sizeof(tmp1)); - char tmp2[strlen(SettingsText(SET_WEBPWD)) + 2]; // Need space for an entered password longer than set password - WebGetArg(PSTR("password"), tmp2, sizeof(tmp2)); - - if (!(!strcmp(tmp1, WEB_USERNAME) && !strcmp(tmp2, SettingsText(SET_WEBPWD)))) { - WSContentBegin(401, CT_APP_JSON); - WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_NEED_USER_AND_PASSWORD "\"}")); - WSContentEnd(); - return; - } - } - WSContentBegin(200, CT_APP_JSON); String svalue = Webserver->arg(F("cmnd")); if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { @@ -2623,80 +2006,6 @@ void HandleHttpCommand(void) WSContentEnd(); } -/*-------------------------------------------------------------------------------------------*/ - -void HandleManagement(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_MANAGEMENT)); - - WSContentStart_P(PSTR(D_MANAGEMENT)); - WSContentSendStyle(); - - WSContentButton(BUTTON_CONSOLE); - - XdrvMailbox.index = 0; - XdrvCall(FUNC_WEB_ADD_CONSOLE_BUTTON); - XsnsCall(FUNC_WEB_ADD_CONSOLE_BUTTON); - - WSContentSend_P(PSTR("
")); // 5px padding - XdrvCall(FUNC_WEB_ADD_MANAGEMENT_BUTTON); - - WSContentSpaceButton(BUTTON_MAIN); - WSContentStop(); -} - -void HandleConsole(void) -{ - if (!HttpCheckPriviledgedAccess()) { return; } - - if (Webserver->hasArg(F("c2"))) { // Console refresh requested - HandleConsoleRefresh(); - return; - } - - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONSOLE)); - - WSContentStart_P(PSTR(D_CONSOLE)); - WSContentSend_P(HTTP_SCRIPT_CONSOL, Settings->web_refresh); - WSContentSendStyle(); - WSContentSend_P(HTTP_FORM_CMND); - WSContentSpaceButton((WebUseManagementSubmenu()) ? BUTTON_MANAGEMENT : BUTTON_MAIN); - WSContentStop(); -} - -void HandleConsoleRefresh(void) -{ - String svalue = Webserver->arg(F("c1")); - if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) { - AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str()); - ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCONSOLE); - } - - char stmp[8]; - WebGetArg(PSTR("c2"), stmp, sizeof(stmp)); - uint32_t index = 0; // Initial start, dump all - if (strlen(stmp)) { index = atoi(stmp); } - - WSContentBegin(200, CT_PLAIN); - WSContentSend_P(PSTR("%d}1%d}1"), TasmotaGlobal.log_buffer_pointer, Web.reset_web_log_flag); - if (!Web.reset_web_log_flag) { - index = 0; - Web.reset_web_log_flag = true; - } - bool cflg = (index); - char* line; - size_t len; - while (GetLog(Settings->weblog_level, &index, &line, &len)) { - if (cflg) { WSContentSend_P(PSTR("\n")); } - WSContentSend(line, len -1); - cflg = true; - } - WSContentSend_P(PSTR("}1")); - WSContentEnd(); -} - /********************************************************************************************/ void HandleNotFound(void) @@ -2743,59 +2052,6 @@ bool CaptivePortal(void) /*********************************************************************************************/ -void HandleDeviceInfo(void) { - WSContentBegin(200, CT_APP_JSON); - WSContentSend_P(PSTR("{\"message\":\"Success\", \"data\":{\"nickname\":\"%s\", \"mac\":\"%s\", \"type\":\"%s\"}}"), SettingsText(SET_FRIENDLYNAME1), WiFi.macAddress().c_str(), DEVICE_TYPE); - WSContentEnd(); -} - -void HandleCertsInfo(void) { - if ((strlen(AmazonClientCert) == 0) || strlen(AmazonPrivateKey) == 0) { - WSContentBegin(500, CT_APP_JSON); - WSContentSend_P(PSTR("{\"message\":\"Fail\"}")); - WSContentEnd(); - return; - } - - WSContentBegin(200, CT_APP_JSON); - WSContentSend_P(PSTR("{\"message\":\"Success\", \"data\":{\"cert\":\"%s\", \"key\":\"%s\"}}"), AmazonClientCert, AmazonPrivateKey); - WSContentEnd(); -} - -void HandleCertsConfiguration(void) { - if(!Webserver->hasArg(F("plain"))) { - WSContentBegin(500, CT_APP_JSON); - WSContentSend_P(PSTR("{\"message\":\"Fail\"}")); - WSContentEnd(); - return; - } - - JsonParser parser((char*) Webserver->arg("plain").c_str()); - JsonParserObject stateObject = parser.getRootObject(); - String cert = stateObject["cert"].getStr(); - String key = stateObject["key"].getStr(); - char* certCharType = (char*)cert.c_str(); - char* keyCharType = (char*)key.c_str(); - -/* TODO: 인증서 사이즈 체크 예외코드 작성 - if(cert.length() != 256 || key.length() < 10) { - WSContentBegin(500, CT_APP_JSON); - WSContentSend_P(PSTR("{\"message\":\"Fail\"}")); - WSContentEnd(); - return; - } -*/ - memcpy(AmazonClientCert, certCharType, strlen(certCharType)); - memcpy(AmazonPrivateKey, keyCharType, strlen(keyCharType)); - MqttDisconnect(); - ConvertTlsFile(0); - ConvertTlsFile(1); - - WSContentBegin(200, CT_APP_JSON); - WSContentSend_P(PSTR("{\"message\":\"Success\"}")); - WSContentEnd(); -} - int WebSend(char *buffer) { // [tasmota] POWER1 ON --> Sends http://tasmota/cm?cmnd=POWER1 ON @@ -2906,7 +2162,7 @@ const char kWebCommands[] PROGMEM = "|" // No prefix #if defined(USE_SENDMAIL) || defined(USE_ESP32MAIL) D_CMND_SENDMAIL "|" #endif - D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" + D_CMND_WEBSERVER "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBSENSOR "|" D_CMND_WEBBUTTON "|" D_CMND_CORS; void (* const WebCommand[])(void) PROGMEM = { @@ -2916,7 +2172,7 @@ void (* const WebCommand[])(void) PROGMEM = { #if defined(USE_SENDMAIL) || defined(USE_ESP32MAIL) &CmndSendmail, #endif - &CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, + &CmndWebServer, &CmndWebRefresh, &CmndWebSend, &CmndWebSensor, &CmndWebButton, &CmndCors }; /*********************************************************************************************\ @@ -2970,30 +2226,6 @@ void CmndWebServer(void) } } -void CmndWebPassword(void) -{ - bool show_asterisk = (2 == XdrvMailbox.index); - if (XdrvMailbox.data_len > 0) { - SettingsUpdateText(SET_WEBPWD, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data); - if (!show_asterisk) { - ResponseCmndChar(SettingsText(SET_WEBPWD)); - } - } else { - show_asterisk = true; - } - if (show_asterisk) { - Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); - } -} - -void CmndWeblog(void) -{ - if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_DEBUG_MORE)) { - Settings->weblog_level = XdrvMailbox.payload; - } - ResponseCmndNumber(Settings->weblog_level); -} - void CmndWebRefresh(void) { if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 65000)) { @@ -3011,31 +2243,6 @@ void CmndWebSend(void) } } -void CmndWebColor(void) -{ - if (XdrvMailbox.data_len > 0) { - if (strchr(XdrvMailbox.data, '{') == nullptr) { // If no JSON it must be parameter - if ((XdrvMailbox.data_len > 3) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= COL_LAST)) { - WebHexCode(XdrvMailbox.index -1, XdrvMailbox.data); - } - else if (0 == XdrvMailbox.payload) { - SettingsDefaultWebColor(); - } - } - else { -#ifndef FIRMWARE_MINIMAL // if tasmota-minimal, read only and don't parse JSON - JsonWebColor(XdrvMailbox.data); -#endif // FIRMWARE_MINIMAL - } - } - Response_P(PSTR("{\"" D_CMND_WEBCOLOR "\":[")); - for (uint32_t i = 0; i < COL_LAST; i++) { - if (i) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"#%06x\""), WebColor(i)); - } - ResponseAppend_P(PSTR("]}")); -} - void CmndWebSensor(void) { if (XdrvMailbox.index < MAX_XSNS_DRIVERS) { diff --git a/tasmota/xdrv_01_webserver_secure.ino b/tasmota/xdrv_01_webserver_secure.ino new file mode 100644 index 000000000000..607c23ad3d81 --- /dev/null +++ b/tasmota/xdrv_01_webserver_secure.ino @@ -0,0 +1,382 @@ +struct WEBSECURE { + bool state_HTTPS = false; + bool state_login = false; +} WebSecure; + +void StartWebserverSecure(void) +{ + if (!WebSecure.state_HTTPS) { + if (!WebserverSecure) { + WebserverSecure = new ESP8266WebServerSecure(443); + WebserverSecure->getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey)); + WebserverSecure->getServer().setBufferSizes(1024, 1024); + WebserverSecure->on(F("/lc"), HTTP_GET, HandleCognitoLoginCode); + WebserverSecure->on(F("/certs"), HTTP_POST, HandleCertsConfiguration); + WebserverSecure->on(F("/info"), HTTP_GET, HandleDeviceInfo); + WebserverSecure->on(F("/wifi"), HTTP_POST, HandleWifiConfigurationWithApp); + } + + WebserverSecure->begin(); // Web server start + } + if (!WebSecure.state_HTTPS) { + AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_HTTP "HTTPS" D_WEBSERVER_ACTIVE_ON " %s%s " D_WITH_IP_ADDRESS " %_I"), + NetworkHostname(), (Mdns.begun) ? PSTR(".local") : "", (uint32_t)WiFi.localIP()); + WebSecure.state_HTTPS = true; + } +} + +// TODO: 메모리 회수 코드 추가 +void StopWebserverSecure(void) +{ + if (WebSecure.state_HTTPS) { + WebserverSecure->close(); + WebSecure.state_HTTPS = false; + AddLog(LOG_LEVEL_INFO, PSTR("HTTPS 웹서버 종료")); + } +} + +/*********************************************************************************************/ + +void HttpHeaderCorsSecure(void) +{ + if (strlen(SettingsText(SET_CORS))) { + WebserverSecure->sendHeader(F("Access-Control-Allow-Origin"), SettingsText(SET_CORS)); + } +} + +void WSHeaderSendSecure(void) +{ + char server[32]; + // TODO: ZIoT 버전 변경 + snprintf_P(server, sizeof(server), PSTR("Tasmota/%s (%s)"), TasmotaGlobal.version, GetDeviceHardware().c_str()); + WebserverSecure->sendHeader(F("Server"), server); + WebserverSecure->sendHeader(F("Cache-Control"), F("no-cache, no-store, must-revalidate")); + WebserverSecure->sendHeader(F("Pragma"), F("no-cache")); + WebserverSecure->sendHeader(F("Expires"), F("-1")); + HttpHeaderCorsSecure(); +} + +/********************************************************************************************** +* HTTP Content Page handler +**********************************************************************************************/ + +void WSSendSecure(int code, int ctype, const String& content) +{ + char ct[25]; // strlen("application/octet-stream") +1 = Longest Content type string + WebserverSecure->send(code, GetTextIndexed(ct, sizeof(ct), ctype, kContentTypes), content); +} + +/********************************************************************************************** +* HTTP Content Chunk handler +**********************************************************************************************/ + +void WSContentBeginSecure(int code, int ctype) { + WebserverSecure->client().flush(); + WSHeaderSendSecure(); + WebserverSecure->setContentLength(CONTENT_LENGTH_UNKNOWN); + WSSendSecure(code, ctype, ""); // Signal start of chunked content + Web.chunk_buffer = ""; +} + +void _WSContentSendSecure(const char* content, size_t size) { // Lowest level sendContent for all core versions + WebserverSecure->sendContent(content, size); + +#ifdef USE_DEBUG_DRIVER + ShowFreeMem(PSTR("WSContentSend")); +#endif + DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d"), size); +} + +void _WSContentSendSecure(const String& content) { // Low level sendContent for all core versions + _WSContentSendSecure(content.c_str(), content.length()); +} + +void WSContentFlushSecure(void) { + if (Web.chunk_buffer.length() > 0) { + _WSContentSendSecure(Web.chunk_buffer); // Flush chunk buffer + Web.chunk_buffer = ""; + } +} + +void WSContentSendSecure(const char* content, size_t size) { + WSContentFlushSecure(); + _WSContentSendSecure(content, size); +} + +void _WSContentSendBufferSecure(bool decimal, const char * formatP, va_list arg) { + char* content = ext_vsnprintf_malloc_P(formatP, arg); + if (content == nullptr) { return; } // Avoid crash + + int len = strlen(content); + if (0 == len) { return; } // No content + + if (decimal && (D_DECIMAL_SEPARATOR[0] != '.')) { + for (uint32_t i = 0; i < len; i++) { + if ('.' == content[i]) { + content[i] = D_DECIMAL_SEPARATOR[0]; + } + } + } + + if (len < CHUNKED_BUFFER_SIZE) { // Append chunk buffer with small content + Web.chunk_buffer += content; + len = Web.chunk_buffer.length(); + } + + if (len >= CHUNKED_BUFFER_SIZE) { // Either content or chunk buffer is oversize + WSContentFlushSecure(); // Send chunk buffer before possible content oversize + } + if (strlen(content) >= CHUNKED_BUFFER_SIZE) { // Content is oversize + _WSContentSendSecure(content); // Send content + } + + free(content); +} + +void WSContentSend_PSecure(const char* formatP, ...) { // Content send snprintf_P char data + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + _WSContentSendBufferSecure(false, formatP, arg); + va_end(arg); +} + +void WSContentSend_PDSecure(const char* formatP, ...) { // Content send snprintf_P char data checked for decimal separator + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + _WSContentSendBufferSecure(true, formatP, arg); + va_end(arg); +} + +void WSContentStart_PSecure(const char* title, bool auth) +{ + WSContentBeginSecure(200, CT_HTML); + + if (title != nullptr) { + WSContentSend_PSecure(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsText(SET_DEVICENAME), title); + } +} + +void WSContentStart_PSecure(const char* title) +{ + WSContentStart_PSecure(title, true); +} + +void WSContentSendStyle_PSecure(const char* formatP, ...) +{ + if ( WifiIsInManagerMode() && (!Web.initial_config) ) { + if (WifiConfigCounter()) { + WSContentSend_PSecure(HTTP_SCRIPT_COUNTER); + } + } + //WSContentSend_P(HTTP_SCRIPT_LOADER); + WSContentSend_PSecure(HTTP_HEAD_LAST_SCRIPT); + + WSContentSend_PSecure(HTTP_HEAD_STYLE1, WebColor(COL_FORM), WebColor(COL_INPUT), WebColor(COL_INPUT_TEXT), WebColor(COL_INPUT), + WebColor(COL_INPUT_TEXT), PSTR(""), PSTR(""), WebColor(COL_BACKGROUND)); + WSContentSend_PSecure(HTTP_HEAD_STYLE2, WebColor(COL_BUTTON), WebColor(COL_BUTTON_TEXT), WebColor(COL_BUTTON_HOVER), + WebColor(COL_BUTTON_RESET), WebColor(COL_BUTTON_RESET_HOVER), WebColor(COL_BUTTON_SAVE), WebColor(COL_BUTTON_SAVE_HOVER), + WebColor(COL_BUTTON)); +#ifdef USE_ZIGBEE + WSContentSend_PSecure(HTTP_HEAD_STYLE_ZIGBEE); +#endif // USE_ZIGBEE + if (formatP != nullptr) { + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + _WSContentSendBufferSecure(false, formatP, arg); + va_end(arg); + } + WSContentSend_PSecure(HTTP_HEAD_STYLE_LOADER); + WSContentSend_PSecure(HTTP_HEAD_STYLE3, WebColor(COL_TEXT), +#ifdef FIRMWARE_MINIMAL + WebColor(COL_TEXT_WARNING), +#endif + WebColor(COL_TITLE), + "", SettingsText(SET_DEVICENAME)); + + // SetOption53 - Show hostname and IP address in GUI main menu +#if (RESTART_AFTER_INITIAL_WIFI_CONFIG) + if (Settings->flag3.gui_hostname_ip) { +#else + if ( Settings->flag3.gui_hostname_ip || ( (WiFi.getMode() == WIFI_AP_STA) && (!Web.initial_config) ) ) { +#endif + bool lip = (static_cast(WiFi.localIP()) != 0); + bool sip = (static_cast(WiFi.softAPIP()) != 0); + WSContentSend_PSecure(PSTR("

%s%s (%s%s%s)

"), // tasmota.local (192.168.2.12, 192.168.4.1) + NetworkHostname(), + (Mdns.begun) ? PSTR(".local") : "", + (lip) ? WiFi.localIP().toString().c_str() : "", + (lip && sip) ? ", " : "", + (sip) ? WiFi.softAPIP().toString().c_str() : ""); + } + WSContentSend_PSecure(PSTR("")); +} + +void WSContentSendStyleSecure(void) +{ + WSContentSendStyle_PSecure(nullptr); +} + +void WSContentTextCenterStartSecure(uint32_t color) { + WSContentSend_PSecure(PSTR("
"), color); +} + +void WSContentButtonSecure(uint32_t title_index, bool show=true) +{ + char action[4]; + char title[100]; // Large to accomodate UTF-16 as used by Russian + + WSContentSend_PSecure(PSTR("

"), + GetTextIndexed(confirm, sizeof(confirm), title_index, kButtonConfirm), + (!title_index) ? PSTR("rst") : PSTR("non"), + GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); + } else { + WSContentSend_PSecure(PSTR(">

"), + GetTextIndexed(title, sizeof(title), title_index, kButtonTitle)); + } +} + +void WSContentSpaceButtonSecure(uint32_t title_index, bool show=true) +{ + WSContentSend_PSecure(PSTR("
"),title_index, show ? "block":"none"); // 5px padding + WSContentButtonSecure(title_index, show); +} + +void WSContentSend_TempSecure(const char *types, float f_temperature) { + WSContentSend_PDSecure(HTTP_SNS_F_TEMP, types, Settings->flag2.temperature_resolution, &f_temperature, TempUnit()); +} + +void WSContentSend_VoltageSecure(const char *types, float f_voltage) { + WSContentSend_PDSecure(HTTP_SNS_F_VOLTAGE, types, Settings->flag2.voltage_resolution, &f_voltage); +} + +void WSContentSend_CurrentMASecure(const char *types, float f_current) { + WSContentSend_PDSecure(HTTP_SNS_F_CURRENT_MA, types, Settings->flag2.current_resolution, &f_current); +} + +void WSContentSend_THDSecure(const char *types, float f_temperature, float f_humidity) +{ + WSContentSend_TempSecure(types, f_temperature); + + char parameter[FLOATSZ]; + dtostrfd(f_humidity, Settings->flag2.humidity_resolution, parameter); + WSContentSend_PDSecure(HTTP_SNS_HUM, types, parameter); + dtostrfd(CalcTempHumToDew(f_temperature, f_humidity), Settings->flag2.temperature_resolution, parameter); + WSContentSend_PDSecure(HTTP_SNS_DEW, types, parameter, TempUnit()); +} + +void WSContentEndSecure(void) +{ + WSContentSendSecure("", 0); // Signal end of chunked content + WebserverSecure->client().stop(); +} + +void WSContentStopSecure(void) +{ + if ( WifiIsInManagerMode() && (!Web.initial_config) ) { + if (WifiConfigCounter()) { + WSContentSend_PSecure(HTTP_COUNTER); + } + } + // TODO: ZIoT 버전 변경 + WSContentSend_PSecure(HTTP_END, WiFi.macAddress().c_str(), TasmotaGlobal.version); + WSContentEndSecure(); +} + +/*********************************************************************************************/ + +void HandleCognitoLoginCode(void) +{ + unsigned char authorization_output[TOPSZ] = ""; + unsigned char* authorization_input = (unsigned char*)"3ambmcokjea85jv4ff2hmkb0un:disli84aaq2ggcul27u5334e5pp74v9gu2mp0h4t4pj1ac1c7g9"; + WebSecure.state_login = true; + Serial.print("========================= Cognito code is "); + Serial.println(WebserverSecure->arg("code")); + WebserverSecure->sendHeader(F("Location"), String(F("http://")) + WebserverSecure->client().localIP().toString(), true); + WebserverSecure->send(302, "text/plain", ""); + + //encode_base64(authorization_input,strlen(String((char*)authorization_input).c_str()),authorization_output); + + //WebserverSecure->sendHeader(F("Authorization", String(F("Basic ")) + String((char*)authorization_output).c_str()), true); + //WebserverSecure->sendHeader(F("Content-Type", String(F("application/x-www-form-urlencoded")), true); + + //WebserverSecure->sendHeader(F("Location"), String(F("https://ziot-sonoff-auth.auth.ap-northeast-2.amazoncognito.com/oauth2/token")), true); +} + +void HandleDeviceInfo(void) { + WSContentBeginSecure(200, CT_APP_JSON); + WSContentSend_PSecure(PSTR("{\"message\":\"Success\", \"data\":{\"nickname\":\"%s\", \"mac\":\"%s\", \"type\":\"%s\"}}"), SettingsText(SET_FRIENDLYNAME1), WiFi.macAddress().c_str(), DEVICE_TYPE); + WSContentEndSecure(); +} + +void HandleCertsConfiguration(void) { + if(!WebserverSecure->hasArg(F("plain"))) { + WSContentBeginSecure(500, CT_APP_JSON); + WSContentSend_PSecure(PSTR("{\"message\":\"Fail\"}")); + WSContentEndSecure(); + return; + } + + JsonParser parser((char*) WebserverSecure->arg("plain").c_str()); + JsonParserObject stateObject = parser.getRootObject(); + String cert = stateObject["cert"].getStr(); + String key = stateObject["key"].getStr(); + char* certCharType = (char*)cert.c_str(); + char* keyCharType = (char*)key.c_str(); + +/* TODO: 인증서 사이즈 체크 예외코드 작성 + if(cert.length() != 256 || key.length() < 10) { + WSContentBegin(500, CT_APP_JSON); + WSContentSend_P(PSTR("{\"message\":\"Fail\"}")); + WSContentEnd(); + return; + } +*/ + memcpy(AmazonClientCert, certCharType, strlen(certCharType)); + memcpy(AmazonPrivateKey, keyCharType, strlen(keyCharType)); + MqttDisconnect(); + ConvertTlsFile(0); + ConvertTlsFile(1); + + WSContentBeginSecure(200, CT_APP_JSON); + WSContentSend_PSecure(PSTR("{\"message\":\"Success\"}")); + WSContentEndSecure(); +} + +void HandleWifiConfigurationWithApp(void) { + if(!WebserverSecure->hasArg(F("plain"))) { + WSContentBeginSecure(500, CT_APP_JSON); + WSContentSend_PSecure(PSTR("{\"message\":\"Failed\" \"resason\":\"1\" \"data\":\"Server received empty request message\"}")); + WSContentEndSecure(); + return; + } + + JsonParser parser((char*) WebserverSecure->arg("plain").c_str()); + JsonParserObject stateObject = parser.getRootObject(); + + String ssid = stateObject["ssid1"].getStr(); + String pwd = stateObject["pwd1"].getStr(); + if (ssid.length() || pwd.length()) { + SettingsUpdateText(SET_STASSID1, (char*)ssid.c_str()); + SettingsUpdateText(SET_STAPWD1, (char*)pwd.c_str()); + } + + ssid = stateObject["ssid2"].getStr(); + pwd = stateObject["pwd2"].getStr(); + if (ssid.length() || pwd.length()) { + SettingsUpdateText(SET_STASSID2, (char*)ssid.c_str()); + SettingsUpdateText(SET_STAPWD2, (char*)pwd.c_str()); + } + + WSContentBeginSecure(200, CT_APP_JSON); + WSContentSend_PSecure(PSTR("{\"message\":\"Success\"}")); + WSContentEndSecure(); +} \ No newline at end of file diff --git a/tasmota/xdrv_02_9_mqtt.ino b/tasmota/xdrv_02_9_mqtt.ino index 70f830f7c6b4..5ace464b35d4 100644 --- a/tasmota/xdrv_02_9_mqtt.ino +++ b/tasmota/xdrv_02_9_mqtt.ino @@ -1852,8 +1852,6 @@ const char HTTP_FORM_MQTT2[] PROGMEM = void HandleMqttConfiguration(void) { - if (!HttpCheckPriviledgedAccess()) { return; } - AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_CONFIGURE_MQTT)); if (Webserver->hasArg(F("save"))) { diff --git a/tasmota/xdrv_21_wemo_multi.ino b/tasmota/xdrv_21_wemo_multi.ino index e2e12c6b30b1..280770d8bb2f 100644 --- a/tasmota/xdrv_21_wemo_multi.ino +++ b/tasmota/xdrv_21_wemo_multi.ino @@ -429,33 +429,33 @@ void WemoRespondToMSearch(int echo_type) { bool Xdrv21(uint8_t function) { - bool result = false; - - if (TasmotaGlobal.devices_present && (EMUL_WEMO == Settings->flag2.emulation)) { - switch (function) { - case FUNC_LOOP: - for (uint32_t i = 1; i < numOfWemoSwitch; i++) { // Handle devices web server - wemoDevice[i]->HandleServerLoop(); - } - break; - case FUNC_WEB_ADD_HANDLER: -#ifdef USE_EMULATION_WEMO_DEBUG - AddLog(LOG_LEVEL_DEBUG, PSTR("WMO: Adding handlers for %d devices"), TasmotaGlobal.devices_present); -#endif - // For the first device use the current webserver, for the others.. create a new one listening on a different PortUdp - wemoDevice[numOfWemoSwitch] = new WemoSwitch(1, Webserver); - wemoDevice[numOfWemoSwitch]->RegisterHandlers(); - numOfWemoSwitch++; - - for (uint32_t i = 1; i < TasmotaGlobal.devices_present; i++) { - wemoDevice[numOfWemoSwitch] = new WemoSwitch(i + 1, 8080 + i); - wemoDevice[numOfWemoSwitch]->RegisterHandlers(); - numOfWemoSwitch++; - } - break; - } - } - return result; +// bool result = false; + +// if (TasmotaGlobal.devices_present && (EMUL_WEMO == Settings->flag2.emulation)) { +// switch (function) { +// case FUNC_LOOP: +// for (uint32_t i = 1; i < numOfWemoSwitch; i++) { // Handle devices web server +// wemoDevice[i]->HandleServerLoop(); +// } +// break; +// case FUNC_WEB_ADD_HANDLER: +// #ifdef USE_EMULATION_WEMO_DEBUG +// AddLog(LOG_LEVEL_DEBUG, PSTR("WMO: Adding handlers for %d devices"), TasmotaGlobal.devices_present); +// #endif +// // For the first device use the current webserver, for the others.. create a new one listening on a different PortUdp +// wemoDevice[numOfWemoSwitch] = new WemoSwitch(1, Webserver); +// wemoDevice[numOfWemoSwitch]->RegisterHandlers(); +// numOfWemoSwitch++; + +// for (uint32_t i = 1; i < TasmotaGlobal.devices_present; i++) { +// wemoDevice[numOfWemoSwitch] = new WemoSwitch(i + 1, 8080 + i); +// wemoDevice[numOfWemoSwitch]->RegisterHandlers(); +// numOfWemoSwitch++; +// } +// break; +// } +// } +// return result; } #endif // USE_WEBSERVER && USE_EMULATION && USE_EMULATION_WEMO \ No newline at end of file