|
|
|
@ -13,6 +13,7 @@ Cgi/template routines for configuring non-wifi settings |
|
|
|
|
#include "ini_parser.h" |
|
|
|
|
|
|
|
|
|
#define SET_REDIR_SUC "/cfg/system" |
|
|
|
|
#define SET_REDIR_ERR SET_REDIR_SUC"?err=" |
|
|
|
|
|
|
|
|
|
static bool ICACHE_FLASH_ATTR |
|
|
|
|
verify_admin_pw(const char *pw) |
|
|
|
@ -79,7 +80,7 @@ cgiPersistRestoreHard(HttpdConnData *connData) |
|
|
|
|
return HTTPD_CGI_DONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -------------- Export --------------
|
|
|
|
|
|
|
|
|
|
#define httpdSend_orDie(conn, data, len) do { if (!httpdSend((conn), (data), (len))) return false; } while (0) |
|
|
|
|
|
|
|
|
@ -217,17 +218,154 @@ cgiPersistExport(HttpdConnData *connData) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void iniCb(const char *section, const char *key, const char *value, void *userData) |
|
|
|
|
// -------------- IMPORT --------------
|
|
|
|
|
|
|
|
|
|
struct IniUpload { |
|
|
|
|
TerminalConfigBundle *term_backup; |
|
|
|
|
WiFiConfigBundle *wifi_backup; |
|
|
|
|
SystemConfigBundle *sys_backup; |
|
|
|
|
bool term_ok; |
|
|
|
|
bool wifi_ok; |
|
|
|
|
bool sys_ok; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void ICACHE_FLASH_ATTR iniCb(const char *section, const char *key, const char *value, void *userData) |
|
|
|
|
{ |
|
|
|
|
dbg(">>> SET: [%s] %s = %s", section, key, value); |
|
|
|
|
HttpdConnData *connData = (HttpdConnData *)userData; |
|
|
|
|
struct IniUpload *state; |
|
|
|
|
if (!connData || !connData->cgiData) { |
|
|
|
|
error("userData or state is NULL!"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
state = connData->cgiData; |
|
|
|
|
|
|
|
|
|
// cgi_dbg("%s.%s = %s", section, key, value);
|
|
|
|
|
|
|
|
|
|
httpd_cgi_state ICACHE_FLASH_ATTR |
|
|
|
|
#define X XSET_ASSIGN |
|
|
|
|
|
|
|
|
|
bool suc = true; |
|
|
|
|
bool found = false; |
|
|
|
|
|
|
|
|
|
// notify flag, unused here
|
|
|
|
|
bool uart_changed = false; |
|
|
|
|
|
|
|
|
|
if (streq(section, "terminal")) { |
|
|
|
|
#define XSTRUCT termconf |
|
|
|
|
XTABLE_TERMCONF |
|
|
|
|
#undef XSTRUCT |
|
|
|
|
if (!suc) state->term_ok = false; |
|
|
|
|
} |
|
|
|
|
else if (streq(section, "wifi")) { |
|
|
|
|
#define XSTRUCT wificonf |
|
|
|
|
XTABLE_WIFICONF |
|
|
|
|
#undef XSTRUCT |
|
|
|
|
if (!suc) state->wifi_ok = false; |
|
|
|
|
} |
|
|
|
|
else if (streq(section, "system")) { |
|
|
|
|
#define XSTRUCT sysconf |
|
|
|
|
XTABLE_SYSCONF |
|
|
|
|
#undef XSTRUCT |
|
|
|
|
if (!suc) state->sys_ok = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!found) cgi_warn("Unknown key %s.%s!", section, key); |
|
|
|
|
|
|
|
|
|
#undef X |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ICACHE_FLASH_ATTR |
|
|
|
|
freeIniUploadStruct(HttpdConnData *connData) |
|
|
|
|
{ |
|
|
|
|
cgi_dbg("Free struct..."); |
|
|
|
|
struct IniUpload *state; |
|
|
|
|
if (connData && connData->cgiData) { |
|
|
|
|
state = connData->cgiData; |
|
|
|
|
if (state->sys_backup != NULL) free(state->sys_backup); |
|
|
|
|
if (state->wifi_backup != NULL) free(state->wifi_backup); |
|
|
|
|
if (state->term_backup != NULL) free(state->term_backup); |
|
|
|
|
free(state); |
|
|
|
|
connData->cgiData = NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static httpd_cgi_state ICACHE_FLASH_ATTR |
|
|
|
|
postRecvHdl(HttpdConnData *connData, char *data, int len) |
|
|
|
|
{ |
|
|
|
|
struct IniUpload *state = connData->cgiData; |
|
|
|
|
if (!state) return HTTPD_CGI_DONE; |
|
|
|
|
|
|
|
|
|
// Discard the boundary marker (there is only one)
|
|
|
|
|
char *bdr = connData->post->multipartBoundary; |
|
|
|
|
char *foundat = strstr(data, bdr); |
|
|
|
|
if (foundat != NULL) { |
|
|
|
|
*foundat = '#'; // make it a comment
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cgi_dbg("INI parse - postRecvHdl"); |
|
|
|
|
|
|
|
|
|
ini_parse(data, (size_t) len); |
|
|
|
|
|
|
|
|
|
cgi_dbg("Closing parser"); |
|
|
|
|
ini_parse_end(); |
|
|
|
|
|
|
|
|
|
cgi_dbg("INI parse - end."); |
|
|
|
|
|
|
|
|
|
// abort if bad screen size
|
|
|
|
|
bool tooLarge = (termconf->width*termconf->height > MAX_SCREEN_SIZE); |
|
|
|
|
state->term_ok &= !tooLarge; |
|
|
|
|
if (tooLarge) cgi_warn("Bad term screen size!"); |
|
|
|
|
|
|
|
|
|
bool suc = state->term_ok && state->wifi_ok && state->sys_ok; |
|
|
|
|
|
|
|
|
|
cgi_dbg("Evaluating results..."); |
|
|
|
|
|
|
|
|
|
if (!state->term_ok) cgi_warn("Terminal settings rejected."); |
|
|
|
|
if (!state->wifi_ok) cgi_warn("WiFi settings rejected."); |
|
|
|
|
if (!state->sys_ok) cgi_warn("System settings rejected."); |
|
|
|
|
|
|
|
|
|
if (!suc) { |
|
|
|
|
cgi_warn("Some validation failed, reverting all!"); |
|
|
|
|
memcpy(termconf, state->term_backup, sizeof(TerminalConfigBundle)); |
|
|
|
|
memcpy(wificonf, state->wifi_backup, sizeof(WiFiConfigBundle)); |
|
|
|
|
memcpy(sysconf, state->sys_backup, sizeof(SystemConfigBundle)); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
cgi_dbg("Applying terminal settings"); |
|
|
|
|
terminal_apply_settings(); |
|
|
|
|
cgi_dbg("Applying system settings"); |
|
|
|
|
sysconf_apply_settings(); |
|
|
|
|
cgi_dbg("Applying WiFi settings (scheduling...)"); |
|
|
|
|
wifimgr_apply_settings_later(1000); |
|
|
|
|
|
|
|
|
|
cgi_dbg("Persisting results"); |
|
|
|
|
persist_store(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cgi_dbg("Redirect"); |
|
|
|
|
char buff[100]; |
|
|
|
|
char *b = buff; |
|
|
|
|
if (suc) { |
|
|
|
|
httpdRedirect(connData, SET_REDIR_SUC"?msg=Settings%20loaded%20and%20applied."); |
|
|
|
|
} else { |
|
|
|
|
b += sprintf(b, SET_REDIR_SUC"?errmsg=Errors%%20in:%%20"); |
|
|
|
|
bool comma = false; |
|
|
|
|
if (!state->sys_ok) { |
|
|
|
|
b += sprintf(b, "System%%20config"); |
|
|
|
|
comma = true; |
|
|
|
|
} |
|
|
|
|
if (!state->wifi_ok) { |
|
|
|
|
if (comma) b += sprintf(b, ",%%20"); |
|
|
|
|
b += sprintf(b, "WiFi%%20config"); |
|
|
|
|
} |
|
|
|
|
if (!state->term_ok) { |
|
|
|
|
if (comma) b += sprintf(b, ",%%20"); |
|
|
|
|
b += sprintf(b, "Terminal%%20config"); |
|
|
|
|
} |
|
|
|
|
httpdRedirect(connData, buff); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Clean up.
|
|
|
|
|
freeIniUploadStruct(connData); |
|
|
|
|
return HTTPD_CGI_DONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -240,27 +378,59 @@ postRecvHdl(HttpdConnData *connData, char *data, int len) |
|
|
|
|
httpd_cgi_state ICACHE_FLASH_ATTR |
|
|
|
|
cgiPersistImport(HttpdConnData *connData) |
|
|
|
|
{ |
|
|
|
|
struct IniUpload *state = NULL; |
|
|
|
|
|
|
|
|
|
if (connData->conn == NULL) { |
|
|
|
|
//Connection aborted. Clean up.
|
|
|
|
|
freeIniUploadStruct(connData); |
|
|
|
|
return HTTPD_CGI_DONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
httpdStartResponse(connData, 200); |
|
|
|
|
httpdHeader(connData, "Content-Type", "text/plain"); |
|
|
|
|
httpdEndHeaders(connData); |
|
|
|
|
|
|
|
|
|
char *start = strstr(connData->post->buff, "\r\n\r\n"); |
|
|
|
|
if (start == NULL) { |
|
|
|
|
error("Malformed attachment POST!"); |
|
|
|
|
goto end; |
|
|
|
|
|
|
|
|
|
httpdStartResponse(connData, 400); |
|
|
|
|
httpdHeader(connData, "Content-Type", "text/plain"); |
|
|
|
|
httpdEndHeaders(connData); |
|
|
|
|
httpdSend(connData, "Bad format.", -1); |
|
|
|
|
return HTTPD_CGI_DONE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cgi_info("Starting INI parser for uploaded file..."); |
|
|
|
|
|
|
|
|
|
state = malloc(sizeof(struct IniUpload)); |
|
|
|
|
if (!state) { |
|
|
|
|
error("state struct alloc fail"); |
|
|
|
|
return HTTPD_CGI_DONE; |
|
|
|
|
} |
|
|
|
|
state->sys_backup = NULL; |
|
|
|
|
state->wifi_backup = NULL; |
|
|
|
|
state->term_backup = NULL; |
|
|
|
|
connData->cgiData = state; |
|
|
|
|
|
|
|
|
|
cgi_dbg("Allocating backup buffers"); |
|
|
|
|
state->sys_backup = malloc(sizeof(SystemConfigBundle)); |
|
|
|
|
state->wifi_backup = malloc(sizeof(WiFiConfigBundle)); |
|
|
|
|
state->term_backup = malloc(sizeof(TerminalConfigBundle)); |
|
|
|
|
|
|
|
|
|
cgi_dbg("Copying orig data"); |
|
|
|
|
memcpy(state->sys_backup, sysconf, sizeof(SystemConfigBundle)); |
|
|
|
|
memcpy(state->wifi_backup, wificonf, sizeof(WiFiConfigBundle)); |
|
|
|
|
memcpy(state->term_backup, termconf, sizeof(TerminalConfigBundle)); |
|
|
|
|
|
|
|
|
|
ini_parse_begin(iniCb, NULL); |
|
|
|
|
ini_parse(start, (size_t) connData->post->buffLen - (start - connData->post->buff)); |
|
|
|
|
state->sys_ok = true; |
|
|
|
|
state->wifi_ok = true; |
|
|
|
|
state->term_ok = true; |
|
|
|
|
|
|
|
|
|
cgi_dbg("Parser starts!"); |
|
|
|
|
ini_parse_begin(iniCb, connData); |
|
|
|
|
|
|
|
|
|
size_t datalen = (size_t) connData->post->buffLen - (start - connData->post->buff); |
|
|
|
|
ini_parse(start, datalen); |
|
|
|
|
|
|
|
|
|
connData->recvHdl = postRecvHdl; |
|
|
|
|
|
|
|
|
|
end: |
|
|
|
|
// TODO redirect
|
|
|
|
|
return HTTPD_CGI_DONE; |
|
|
|
|
// continues in recvHdl
|
|
|
|
|
return HTTPD_CGI_MORE; |
|
|
|
|
} |
|
|
|
|