mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-08-01 06:52:03 +08:00
1741 lines
65 KiB
C++
1741 lines
65 KiB
C++
/*
|
|
webinterface.cpp - ESP3D configuration class
|
|
|
|
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <pgmspace.h>
|
|
#include "config.h"
|
|
#include "webinterface.h"
|
|
#include "wificonf.h"
|
|
#include <WiFiClient.h>
|
|
#include <WiFiServer.h>
|
|
#include <WiFiUdp.h>
|
|
#ifndef FS_NO_GLOBALS
|
|
#define FS_NO_GLOBALS
|
|
#endif
|
|
#include <FS.h>
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
#include "ESP8266WiFi.h"
|
|
#include <ESP8266WebServer.h>
|
|
#else
|
|
#include <WiFi.h>
|
|
#include <WebServer.h>
|
|
#include "SPIFFS.h"
|
|
#include "Update.h"
|
|
#endif
|
|
|
|
#include "GenLinkedList.h"
|
|
#include "storestrings.h"
|
|
#include "command.h"
|
|
#include "bridge.h"
|
|
|
|
#ifdef SSDP_FEATURE
|
|
#include <ESP8266SSDP.h>
|
|
#endif
|
|
|
|
//embedded response file if no files on SPIFFS
|
|
#include "nofile.h"
|
|
|
|
#define MAX_AUTH_IP 10
|
|
#define HIDDEN_PASSWORD "********"
|
|
|
|
|
|
typedef enum {
|
|
UPLOAD_STATUS_NONE = 0,
|
|
UPLOAD_STATUS_FAILED = 1,
|
|
UPLOAD_STATUS_CANCELLED = 2,
|
|
UPLOAD_STATUS_SUCCESSFUL = 3,
|
|
UPLOAD_STATUS_ONGOING =4
|
|
} upload_status_type;
|
|
|
|
const char PAGE_404 [] PROGMEM ="<HTML>\n<HEAD>\n<title>Redirecting...</title> \n</HEAD>\n<BODY>\n<CENTER>Unknown page : $QUERY$- you will be redirected...\n<BR><BR>\nif not redirected, <a href='http://$WEB_ADDRESS$'>click here</a>\n<BR><BR>\n<PROGRESS name='prg' id='prg'></PROGRESS>\n\n<script>\nvar i = 0; \nvar x = document.getElementById(\"prg\"); \nx.max=5; \nvar interval=setInterval(function(){\ni=i+1; \nvar x = document.getElementById(\"prg\"); \nx.value=i; \nif (i>5) \n{\nclearInterval(interval);\nwindow.location.href='/';\n}\n},1000);\n</script>\n</CENTER>\n</BODY>\n</HTML>\n\n";
|
|
const char PAGE_CAPTIVE [] PROGMEM ="<HTML>\n<HEAD>\n<title>Captive Portal</title> \n</HEAD>\n<BODY>\n<CENTER>Captive Portal page : $QUERY$- you will be redirected...\n<BR><BR>\nif not redirected, <a href='http://$WEB_ADDRESS$'>click here</a>\n<BR><BR>\n<PROGRESS name='prg' id='prg'></PROGRESS>\n\n<script>\nvar i = 0; \nvar x = document.getElementById(\"prg\"); \nx.max=5; \nvar interval=setInterval(function(){\ni=i+1; \nvar x = document.getElementById(\"prg\"); \nx.value=i; \nif (i>5) \n{\nclearInterval(interval);\nwindow.location.href='/';\n}\n},1000);\n</script>\n</CENTER>\n</BODY>\n</HTML>\n\n";
|
|
const char CONTENT_TYPE_HTML [] PROGMEM ="text/html";
|
|
|
|
void handle_web_interface_root()
|
|
{
|
|
String path = "/index.html";
|
|
String contentType = web_interface->getContentType(path);
|
|
String pathWithGz = path + ".gz";
|
|
//if have a index.html or gzip version this is default root page
|
|
if((SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) && !web_interface->web_server.hasArg("fallback") && web_interface->web_server.arg("forcefallback")!="yes") {
|
|
if(SPIFFS.exists(pathWithGz)) {
|
|
path = pathWithGz;
|
|
}
|
|
FS_FILE file = SPIFFS.open(path, SPIFFS_FILE_READ);
|
|
web_interface->web_server.streamFile(file, contentType);
|
|
file.close();
|
|
return;
|
|
}
|
|
//if no lets launch the default content
|
|
web_interface->web_server.sendHeader("Content-Encoding", "gzip");
|
|
web_interface->web_server.send_P(200,CONTENT_TYPE_HTML,PAGE_NOFILES,PAGE_NOFILES_SIZE);
|
|
}
|
|
|
|
//concat several catched informations temperatures/position/status/flow/speed
|
|
void handle_web_interface_status()
|
|
{
|
|
// static const char NO_TEMP_LINE[] PROGMEM = "\"temperature\":\"0\",\"target\":\"0\",\"active\":\"0\"";
|
|
//we do not care if need authentication - just reset counter
|
|
web_interface->is_authenticated();
|
|
//int tagpos,tagpos2;
|
|
String buffer2send;
|
|
String value;
|
|
//start JSON answer
|
|
buffer2send="{";
|
|
#ifdef INFO_MSG_FEATURE
|
|
//information
|
|
buffer2send.concat(F("\"InformationMsg\":["));
|
|
|
|
for (int i=0; i<web_interface->info_msg.size(); i++) {
|
|
if (i>0) {
|
|
buffer2send+=",";
|
|
}
|
|
buffer2send+="{\"line\":\"";
|
|
buffer2send+=web_interface->info_msg.get(i);
|
|
buffer2send+="\"}";
|
|
}
|
|
buffer2send+="],";
|
|
#endif
|
|
#ifdef ERROR_MSG_FEATURE
|
|
//Error
|
|
buffer2send.concat(F("\"ErrorMsg\":["));
|
|
for (int i=0; i<web_interface->error_msg.size(); i++) {
|
|
if (i>0) {
|
|
buffer2send+=",";
|
|
}
|
|
buffer2send+="{\"line\":\"";
|
|
buffer2send+=web_interface->error_msg.get(i);
|
|
buffer2send+="\"}";
|
|
}
|
|
buffer2send+="],";
|
|
#endif
|
|
#ifdef STATUS_MSG_FEATURE
|
|
//Status
|
|
buffer2send.concat(F("\"StatusMsg\":["));
|
|
|
|
for (int i=0; i<web_interface->status_msg.size(); i++) {
|
|
if (i>0) {
|
|
buffer2send+=",";
|
|
}
|
|
buffer2send+="{\"line\":\"";
|
|
buffer2send+=web_interface->status_msg.get(i);
|
|
buffer2send+="\"}";
|
|
}
|
|
buffer2send+="],";
|
|
#endif
|
|
//status color
|
|
buffer2send+="\"status\":\""+value +"\"";
|
|
buffer2send+="}";
|
|
web_interface->web_server.sendHeader("Cache-Control", "no-cache");
|
|
web_interface->web_server.send(200, "application/json",buffer2send);
|
|
}
|
|
|
|
//SPIFFS files uploader handle
|
|
void SPIFFSFileupload()
|
|
{
|
|
#ifdef DEBUG_PERFORMANCE
|
|
static uint32_t startupload;
|
|
static uint32_t write_time;
|
|
static size_t filesize;
|
|
#endif
|
|
//get authentication status
|
|
level_authenticate_type auth_level= web_interface->is_authenticated();
|
|
//Guest cannot upload
|
|
if (auth_level == LEVEL_GUEST) {
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
ESP_SERIAL_OUT.println("M117 Error ESP upload");
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
web_interface->web_server.client().stopAll();
|
|
#else
|
|
web_interface->web_server.client().stop();
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
static String filename;
|
|
//get current file ID
|
|
HTTPUpload& upload = (web_interface->web_server).upload();
|
|
//Upload start
|
|
//**************
|
|
if(upload.status == UPLOAD_FILE_START) {
|
|
#ifdef DEBUG_PERFORMANCE
|
|
startupload = millis();
|
|
write_time = 0;
|
|
filesize = 0;
|
|
#endif
|
|
//according User or Admin the root is different as user is isolate to /user when admin has full access
|
|
if(auth_level == LEVEL_ADMIN) {
|
|
filename = upload.filename;
|
|
} else {
|
|
filename = "/user" + upload.filename;
|
|
}
|
|
ESP_SERIAL_OUT.println("M117 Start ESP upload");
|
|
//create file
|
|
web_interface->fsUploadFile = SPIFFS.open(filename, SPIFFS_FILE_WRITE);
|
|
//check If creation succeed
|
|
if (web_interface->fsUploadFile) {
|
|
//if yes upload is started
|
|
web_interface->_upload_status= UPLOAD_STATUS_ONGOING;
|
|
} else {
|
|
//if no set cancel flag
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
ESP_SERIAL_OUT.println("M117 Error ESP create");
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
web_interface->web_server.client().stopAll();
|
|
#else
|
|
web_interface->web_server.client().stop();
|
|
#endif
|
|
}
|
|
//Upload write
|
|
//**************
|
|
} else if(upload.status == UPLOAD_FILE_WRITE) {
|
|
//check if file is available and no error
|
|
if(web_interface->fsUploadFile && web_interface->_upload_status == UPLOAD_STATUS_ONGOING) {
|
|
#ifdef DEBUG_PERFORMANCE
|
|
filesize+=upload.currentSize;
|
|
uint32_t startwrite = millis();
|
|
#endif
|
|
//no error so write post date
|
|
web_interface->fsUploadFile.write(upload.buf, upload.currentSize);
|
|
#ifdef DEBUG_PERFORMANCE
|
|
write_time += (millis()-startwrite);
|
|
#endif
|
|
} else {
|
|
//we have a problem set flag UPLOAD_STATUS_CANCELLED
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
web_interface->web_server.client().stopAll();
|
|
#else
|
|
web_interface->web_server.client().stop();
|
|
#endif
|
|
ESP_SERIAL_OUT.println("M117 Error ESP write");
|
|
}
|
|
//Upload end
|
|
//**************
|
|
} else if(upload.status == UPLOAD_FILE_END) {
|
|
#ifdef DEBUG_PERFORMANCE
|
|
uint32_t endupload = millis();
|
|
DEBUG_PERF_VARIABLE.add(String(endupload-startupload).c_str());
|
|
DEBUG_PERF_VARIABLE.add(String(write_time).c_str());
|
|
DEBUG_PERF_VARIABLE.add(String(filesize).c_str());
|
|
#endif
|
|
ESP_SERIAL_OUT.println("M117 End ESP upload");
|
|
//check if file is still open
|
|
if(web_interface->fsUploadFile) {
|
|
//close it
|
|
web_interface->fsUploadFile.close();
|
|
web_interface->_upload_status=UPLOAD_STATUS_SUCCESSFUL;
|
|
} else {
|
|
//we have a problem set flag UPLOAD_STATUS_CANCELLED
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
web_interface->web_server.client().stopAll();
|
|
#else
|
|
web_interface->web_server.client().stop();
|
|
#endif
|
|
SPIFFS.remove(filename);
|
|
ESP_SERIAL_OUT.println("M117 Error ESP close");
|
|
}
|
|
//Upload cancelled
|
|
//**************
|
|
} else {
|
|
ESP_SERIAL_OUT.println("M117 Error ESP close");
|
|
return;
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
SPIFFS.remove(filename);
|
|
ESP_SERIAL_OUT.println("M117 Error ESP upload");
|
|
}
|
|
delay(0);
|
|
}
|
|
|
|
#define NB_RETRY 5
|
|
#define MAX_RESEND_BUFFER 128
|
|
//SD file upload by serial
|
|
void SDFile_serial_upload()
|
|
{
|
|
static char buffer_line[MAX_RESEND_BUFFER]; //if need to resend
|
|
static char previous = 0;
|
|
static int buffer_size;
|
|
static bool com_error = false;
|
|
static bool is_comment = false;
|
|
bool client_closed = false;
|
|
static String filename;
|
|
String response;
|
|
//Guest cannot upload - only admin and user
|
|
if(web_interface->is_authenticated() == LEVEL_GUEST) {
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
ESP_SERIAL_OUT.println("M117 SD upload rejected");
|
|
LOG("SD upload rejected\r\n");
|
|
if (!client_closed){
|
|
//web_interface->web_server.client().stopAll();
|
|
LOG("Need to stop");
|
|
client_closed = true;
|
|
}
|
|
return;
|
|
}
|
|
#ifdef DEBUG_PERFORMANCE
|
|
static uint32_t startupload;
|
|
static uint32_t write_time;
|
|
static size_t filesize;
|
|
#endif
|
|
//retrieve current file id
|
|
HTTPUpload& upload = (web_interface->web_server).upload();
|
|
//Upload start
|
|
//**************
|
|
if(upload.status == UPLOAD_FILE_START) {
|
|
//need to lock serial out to avoid garbage in file
|
|
(web_interface->blockserial) = true;
|
|
//init flags
|
|
buffer_size=0;
|
|
com_error = false;
|
|
is_comment = false;
|
|
previous = 0;
|
|
web_interface->_upload_status= UPLOAD_STATUS_ONGOING;
|
|
ESP_SERIAL_OUT.println("M117 Uploading...");
|
|
ESP_SERIAL_OUT.flush();
|
|
#ifdef DEBUG_PERFORMANCE
|
|
startupload = millis();
|
|
write_time = 0;
|
|
filesize = 0;
|
|
#endif
|
|
LOG("Clear Serial\r\n");
|
|
if(ESP_SERIAL_OUT.available()) {
|
|
//get size of buffer
|
|
size_t len = ESP_SERIAL_OUT.available();
|
|
uint8_t sbuf[len+1];
|
|
//read buffer
|
|
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
|
//convert buffer to zero end array
|
|
sbuf[len]='\0';
|
|
//use string because easier to handle
|
|
response = (const char*)sbuf;
|
|
LOG(response);
|
|
LOG("\r\n");
|
|
}
|
|
//command to pritnter to start print
|
|
String command = "M28 " + upload.filename;
|
|
LOG(command);
|
|
LOG("\r\n");
|
|
ESP_SERIAL_OUT.println(command);
|
|
ESP_SERIAL_OUT.flush();
|
|
filename = upload.filename;
|
|
//now need to purge all serial data
|
|
//let's sleep 1s
|
|
//delay(1000);
|
|
for (int retry=0; retry < 400; retry++) { //time out is 5x400ms = 2000ms
|
|
//if there is something in serial buffer
|
|
if(ESP_SERIAL_OUT.available()) {
|
|
//get size of buffer
|
|
size_t len = ESP_SERIAL_OUT.available();
|
|
uint8_t sbuf[len+1];
|
|
//read buffer
|
|
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
|
//convert buffer to zero end array
|
|
sbuf[len]='\0';
|
|
//use string because easier to handle
|
|
response =(const char*)sbuf;
|
|
LOG(response);
|
|
//if there is a wait it means purge is done
|
|
if (response.indexOf("wait")>-1) {
|
|
LOG("Exit start writing\r\n");
|
|
break;
|
|
}
|
|
if (response.indexOf("Resend")>-1 || response.indexOf("failed")>-1) {
|
|
com_error = true;
|
|
web_interface->blockserial = false;
|
|
LOG("Error start writing\r\n");
|
|
break;
|
|
}
|
|
}
|
|
delay(5);
|
|
}
|
|
//Upload write
|
|
//**************
|
|
//upload is on going with data coming by 2K blocks
|
|
} else if((upload.status == UPLOAD_FILE_WRITE) && (com_error == false)) { //if com error no need to send more data to serial
|
|
web_interface->_upload_status= UPLOAD_STATUS_ONGOING;
|
|
#ifdef DEBUG_PERFORMANCE
|
|
filesize+=upload.currentSize;
|
|
uint32_t startwrite = millis();
|
|
#endif
|
|
for (int pos = 0; pos < upload.currentSize; pos++) { //parse full post data
|
|
if (buffer_size < MAX_RESEND_BUFFER-1) { //raise error/handle if overbuffer - copy is space available
|
|
//remove/ignore every comment to save transfert time and avoid over buffer issues
|
|
if (upload.buf[pos] == ';') {
|
|
is_comment = true;
|
|
previous = ';';
|
|
}
|
|
if (!is_comment) {
|
|
buffer_line[buffer_size] = upload.buf[pos]; //copy current char to buffer to send/resend
|
|
buffer_size++;
|
|
//convert buffer to zero end array
|
|
buffer_line[buffer_size] = '\0';
|
|
//check it is not an end line char and line is not empty
|
|
if (((buffer_line[0] == '\n') && (buffer_size==1)) ||((buffer_line[1] == '\n') && (buffer_line[0] == '\r') && (buffer_size==2)) || ((buffer_line[0] == ' ') && (buffer_size==1)) ) {
|
|
//ignore empty line
|
|
buffer_size=0;
|
|
buffer_line[buffer_size] = '\0';
|
|
}
|
|
//line is not empty so check if last char is an end line
|
|
//if error no need to proceed
|
|
else if (((buffer_line[buffer_size-1] == '\n')) && (com_error == false)) { //end of line and no error
|
|
//if resend use buffer
|
|
bool success = false;
|
|
|
|
//check NB_RETRY times if get no error when send line
|
|
for (int r = 0 ; r < NB_RETRY ; r++) {
|
|
response = "";
|
|
//print out line
|
|
ESP_SERIAL_OUT.print(buffer_line);
|
|
LOG(buffer_line);
|
|
//ensure buffer is empty before continuing
|
|
ESP_SERIAL_OUT.flush();
|
|
//wait for answer with time out
|
|
for (int retry=0; retry < 30; retry++) { //time out 30x5ms = 150ms
|
|
//if there is serial data
|
|
if(ESP_SERIAL_OUT.available()) {
|
|
//get size of available data
|
|
size_t len = ESP_SERIAL_OUT.available();
|
|
uint8_t sbuf[len+1];
|
|
//read serial buffer
|
|
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
|
//convert buffer in zero end array
|
|
sbuf[len]='\0';
|
|
//use string because easier
|
|
response = (const char*)sbuf;
|
|
LOG("Retry:");
|
|
LOG(String(retry));
|
|
LOG("\r\n");
|
|
LOG(response);
|
|
//if buffer contain ok or wait - it means command is pass
|
|
if ((response.indexOf("wait")>-1)||(response.indexOf("ok")>-1)) {
|
|
success = true;
|
|
break;
|
|
}
|
|
//if buffer contain resend then need to resend
|
|
if (response.indexOf("Resend") > -1) { //if error
|
|
success = false;
|
|
break;
|
|
}
|
|
}
|
|
delay(5);
|
|
}
|
|
//if command is pass no need to retry
|
|
if (success == true) {
|
|
break;
|
|
}
|
|
//purge extra serial if any
|
|
if(ESP_SERIAL_OUT.available()) {
|
|
//get size of available data
|
|
size_t len = ESP_SERIAL_OUT.available();
|
|
uint8_t sbuf[len+1];
|
|
//read serial buffer
|
|
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
|
//convert buffer in zero end array
|
|
sbuf[len]='\0';
|
|
}
|
|
}
|
|
//if even after the number of retry still have error - then we are in error
|
|
if (!success) {
|
|
//raise error
|
|
LOG("Error detected\r\n");
|
|
LOG(response);
|
|
com_error = true;
|
|
}
|
|
//reset buffer for next command
|
|
buffer_size = 0;
|
|
buffer_line[buffer_size] = '\0';
|
|
}
|
|
} else { //it is a comment
|
|
if (upload.buf[pos] == '\r') { //store if CR
|
|
previous = '\r';
|
|
} else if (upload.buf[pos] == '\n') { //this is the end of the comment
|
|
is_comment = false;
|
|
if (buffer_size > 0) {
|
|
if (previous == '\r') {
|
|
pos--;
|
|
}
|
|
pos--; //do a loop back and process as normal
|
|
}
|
|
previous = '\n';
|
|
}//if not just ignore and continue
|
|
else {
|
|
previous = upload.buf[pos];
|
|
}
|
|
|
|
}
|
|
} else { //raise error
|
|
LOG("\r\nlong line detected\r\n");
|
|
LOG(buffer_line);
|
|
com_error = true;
|
|
}
|
|
}
|
|
#ifdef DEBUG_PERFORMANCE
|
|
write_time += (millis()-startwrite);
|
|
#endif
|
|
//Upload end
|
|
//**************
|
|
} else if(upload.status == UPLOAD_FILE_END) {
|
|
if (buffer_size > 0) { //if last part does not have '\n'
|
|
//print the line
|
|
ESP_SERIAL_OUT.print(buffer_line);
|
|
if (is_comment && (previous == '\r')) {
|
|
ESP_SERIAL_OUT.print("\r\n");
|
|
} else {
|
|
ESP_SERIAL_OUT.print("\n");
|
|
}
|
|
ESP_SERIAL_OUT.flush();
|
|
//if resend use buffer
|
|
bool success = false;
|
|
//check NB_RETRY times if get no error when send line
|
|
for (int r = 0 ; r < NB_RETRY ; r++) {
|
|
response = "";
|
|
ESP_SERIAL_OUT.print(buffer_line);
|
|
ESP_SERIAL_OUT.flush();
|
|
//wait for answer with time out
|
|
for (int retry=0; retry < 20; retry++) { //time out
|
|
if(ESP_SERIAL_OUT.available()) {
|
|
size_t len = ESP_SERIAL_OUT.available();
|
|
uint8_t sbuf[len+1];
|
|
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
|
sbuf[len]='\0';
|
|
response = (const char*)sbuf;
|
|
if ((response.indexOf("wait")>-1)||(response.indexOf("ok")>-1)) {
|
|
success = true;
|
|
break;
|
|
}
|
|
if (response.indexOf("Resend") > -1) { //if error
|
|
success = false;
|
|
break;
|
|
}
|
|
}
|
|
delay(5);
|
|
}
|
|
if (success == true) {
|
|
break;
|
|
}
|
|
}
|
|
if (!success) {
|
|
//raise error
|
|
LOG("Error detected 2\r\n");
|
|
LOG(response);
|
|
com_error = true;
|
|
}
|
|
//reset buffer for next command
|
|
buffer_size = 0;
|
|
buffer_line[buffer_size] = '\0';
|
|
|
|
}
|
|
LOG("Upload finished ");
|
|
buffer_size=0;
|
|
buffer_line[buffer_size] = '\0';
|
|
//send M29 command to close file on SD
|
|
ESP_SERIAL_OUT.print("\r\nM29\r\n");
|
|
ESP_SERIAL_OUT.flush();
|
|
web_interface->blockserial = false;
|
|
delay(1000);//give time to FW
|
|
//resend M29 command to close file on SD as first command may be lost
|
|
ESP_SERIAL_OUT.print("\r\nM29\r\n");
|
|
ESP_SERIAL_OUT.flush();
|
|
#ifdef DEBUG_PERFORMANCE
|
|
uint32_t endupload = millis();
|
|
DEBUG_PERF_VARIABLE.add(String(endupload-startupload).c_str());
|
|
DEBUG_PERF_VARIABLE.add(String(write_time).c_str());
|
|
DEBUG_PERF_VARIABLE.add(String(filesize).c_str());
|
|
#endif
|
|
if (com_error) {
|
|
web_interface->blockserial = false;
|
|
LOG("with error\r\n");
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
if (!client_closed){
|
|
//web_interface->web_server.client().stopAll();
|
|
LOG("Need to stop");
|
|
client_closed = true;
|
|
}
|
|
filename = "M30 " + filename;
|
|
ESP_SERIAL_OUT.println(filename);
|
|
ESP_SERIAL_OUT.println("M117 SD upload failed");
|
|
ESP_SERIAL_OUT.flush();
|
|
|
|
} else {
|
|
LOG("with success\r\n");
|
|
web_interface->_upload_status=UPLOAD_STATUS_SUCCESSFUL;
|
|
ESP_SERIAL_OUT.println("M117 SD upload done");
|
|
ESP_SERIAL_OUT.flush();
|
|
}
|
|
//Upload cancelled
|
|
//**************
|
|
} else { //UPLOAD_FILE_ABORTED
|
|
LOG("Error, Something happened\r\n");
|
|
com_error = true;
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
buffer_size=0;
|
|
buffer_line[buffer_size] = '\0';
|
|
//send M29 command to close file on SD
|
|
ESP_SERIAL_OUT.print("\r\nM29\r\n");
|
|
ESP_SERIAL_OUT.flush();
|
|
web_interface->blockserial = false;
|
|
delay(1000);
|
|
//resend M29 command to close file on SD as first command may be lost
|
|
ESP_SERIAL_OUT.print("\r\nM29\r\n");
|
|
ESP_SERIAL_OUT.flush();
|
|
filename = "M30 " + filename;
|
|
ESP_SERIAL_OUT.println(filename);
|
|
ESP_SERIAL_OUT.println("M117 SD upload failed");
|
|
ESP_SERIAL_OUT.flush();
|
|
}
|
|
}
|
|
|
|
|
|
//FW update using Web interface
|
|
#ifdef WEB_UPDATE_FEATURE
|
|
void WebUpdateUpload()
|
|
{
|
|
static size_t last_upload_update;
|
|
static uint32_t maxSketchSpace ;
|
|
//only admin can update FW
|
|
if(web_interface->is_authenticated() != LEVEL_ADMIN) {
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
web_interface->web_server.client().stopAll();
|
|
#else
|
|
web_interface->web_server.client().stop();
|
|
#endif
|
|
ESP_SERIAL_OUT.println("M117 Update failed");
|
|
LOG("SD Update failed\r\n");
|
|
return;
|
|
}
|
|
//get current file ID
|
|
HTTPUpload& upload = (web_interface->web_server).upload();
|
|
//Upload start
|
|
//**************
|
|
if(upload.status == UPLOAD_FILE_START) {
|
|
ESP_SERIAL_OUT.println(F("M117 Update Firmware"));
|
|
web_interface->_upload_status= UPLOAD_STATUS_ONGOING;
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
WiFiUDP::stopAll();
|
|
#endif
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
|
|
#else
|
|
//Not sure can do OTA on 2Mb board
|
|
maxSketchSpace = (ESP.getFlashChipSize()>0x20000)?0x140000:0x140000/2;
|
|
#endif
|
|
last_upload_update = 0;
|
|
if(!Update.begin(maxSketchSpace)) { //start with max available size
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
} else {
|
|
if (( CONFIG::GetFirmwareTarget() == REPETIER4DV) || (CONFIG::GetFirmwareTarget() == REPETIER)) ESP_SERIAL_OUT.println(F("M117 Update 0%%"));
|
|
else ESP_SERIAL_OUT.println(F("M117 Update 0%"));
|
|
}
|
|
//Upload write
|
|
//**************
|
|
} else if(upload.status == UPLOAD_FILE_WRITE) {
|
|
//check if no error
|
|
if (web_interface->_upload_status == UPLOAD_STATUS_ONGOING) {
|
|
//we do not know the total file size yet but we know the available space so let's use it
|
|
if ( ((100 * upload.totalSize) / maxSketchSpace) !=last_upload_update) {
|
|
last_upload_update = (100 * upload.totalSize) / maxSketchSpace;
|
|
ESP_SERIAL_OUT.print(F("M117 Update "));
|
|
ESP_SERIAL_OUT.print(last_upload_update);
|
|
if (( CONFIG::GetFirmwareTarget() == REPETIER4DV) || (CONFIG::GetFirmwareTarget() == REPETIER)) ESP_SERIAL_OUT.println(F("%%"));
|
|
else ESP_SERIAL_OUT.println(F("%"));
|
|
}
|
|
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
}
|
|
}
|
|
//Upload end
|
|
//**************
|
|
} else if(upload.status == UPLOAD_FILE_END) {
|
|
if(Update.end(true)) { //true to set the size to the current progress
|
|
//Now Reboot
|
|
if (( CONFIG::GetFirmwareTarget() == REPETIER4DV) || (CONFIG::GetFirmwareTarget() == REPETIER)) ESP_SERIAL_OUT.println(F("M117 Update 100%%"));
|
|
else ESP_SERIAL_OUT.println(F("M117 Update 100%"));
|
|
web_interface->_upload_status=UPLOAD_STATUS_SUCCESSFUL;
|
|
}
|
|
} else if(upload.status == UPLOAD_FILE_ABORTED) {
|
|
ESP_SERIAL_OUT.println(F("M117 Update Failed"));
|
|
Update.end();
|
|
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
|
|
}
|
|
delay(0);
|
|
}
|
|
|
|
void handleUpdate()
|
|
{
|
|
level_authenticate_type auth_level = web_interface->is_authenticated();
|
|
if (auth_level != LEVEL_ADMIN) {
|
|
web_interface->_upload_status=UPLOAD_STATUS_NONE;
|
|
web_interface->web_server.send(403,"text/plain","Not allowed, log in first!\n");
|
|
return;
|
|
}
|
|
String jsonfile = "{\"status\":\"" ;
|
|
jsonfile+=CONFIG::intTostr(web_interface->_upload_status);
|
|
jsonfile+="\"}";
|
|
//send status
|
|
web_interface->web_server.sendHeader("Cache-Control", "no-cache");
|
|
web_interface->web_server.send(200, "application/json", jsonfile);
|
|
//if success restart
|
|
if (web_interface->_upload_status==UPLOAD_STATUS_SUCCESSFUL) {
|
|
web_interface->restartmodule=true;
|
|
} else {
|
|
web_interface->_upload_status=UPLOAD_STATUS_NONE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//SPIFFS files list and file commands
|
|
void handleFileList()
|
|
{
|
|
level_authenticate_type auth_level = web_interface->is_authenticated();
|
|
if (auth_level == LEVEL_GUEST) {
|
|
web_interface->_upload_status=UPLOAD_STATUS_NONE;
|
|
web_interface->web_server.send(401,"text/plain","Authentication failed!\n");
|
|
return;
|
|
}
|
|
String path ;
|
|
String status = "Ok";
|
|
if ((web_interface->_upload_status == UPLOAD_STATUS_FAILED) || (web_interface->_upload_status == UPLOAD_STATUS_CANCELLED)) {
|
|
status = "Upload failed";
|
|
}
|
|
//be sure root is correct according authentication
|
|
if (auth_level == LEVEL_ADMIN) {
|
|
path = "/";
|
|
} else {
|
|
path = "/user";
|
|
}
|
|
//get current path
|
|
if(web_interface->web_server.hasArg("path")) {
|
|
path += web_interface->web_server.arg("path") ;
|
|
}
|
|
//to have a clean path
|
|
path.trim();
|
|
path.replace("//","/");
|
|
if (path[path.length()-1] !='/') {
|
|
path +="/";
|
|
}
|
|
//check if query need some action
|
|
if(web_interface->web_server.hasArg("action")) {
|
|
//delete a file
|
|
if(web_interface->web_server.arg("action") == "delete" && web_interface->web_server.hasArg("filename")) {
|
|
String filename;
|
|
String shortname = web_interface->web_server.arg("filename");
|
|
shortname.replace("/","");
|
|
filename = path + web_interface->web_server.arg("filename");
|
|
filename.replace("//","/");
|
|
if(!SPIFFS.exists(filename)) {
|
|
status = shortname + F(" does not exists!");
|
|
} else {
|
|
if (SPIFFS.remove(filename)) {
|
|
status = shortname + F(" deleted");
|
|
//what happen if no "/." and no other subfiles ?
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
FS_DIR dir = SPIFFS.openDir(path);
|
|
if (!dir.next()) {
|
|
#else
|
|
String ptmp = path;
|
|
if ((path != "/") && (path[path.length()-1]='/'))ptmp = path.substring(0,path.length()-1);
|
|
FS_FILE dir = SPIFFS.open(ptmp);
|
|
FS_FILE dircontent = dir.openNextFile();
|
|
if (!dircontent) {
|
|
#endif
|
|
//keep directory alive even empty
|
|
FS_FILE r = SPIFFS.open(path+"/.", SPIFFS_FILE_WRITE);
|
|
if (r) {
|
|
r.close();
|
|
}
|
|
}
|
|
} else {
|
|
status = F("Cannot deleted ") ;
|
|
status+=shortname ;
|
|
}
|
|
}
|
|
}
|
|
//delete a directory
|
|
if(web_interface->web_server.arg("action") == "deletedir" && web_interface->web_server.hasArg("filename")) {
|
|
String filename;
|
|
String shortname = web_interface->web_server.arg("filename");
|
|
shortname.replace("/","");
|
|
filename = path + web_interface->web_server.arg("filename");
|
|
filename += "/";
|
|
filename.replace("//","/");
|
|
if (filename != "/") {
|
|
bool delete_error = false;
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
FS_DIR dir = SPIFFS.openDir(path + shortname);
|
|
{
|
|
while (dir.next()) {
|
|
#else
|
|
FS_FILE dir = SPIFFS.open(path + shortname);
|
|
{
|
|
FS_FILE file2deleted = dir.openNextFile();
|
|
while (file2deleted) {
|
|
#endif
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
String fullpath = dir.fileName();
|
|
#else
|
|
String fullpath = file2deleted.name();
|
|
#endif
|
|
if (!SPIFFS.remove(fullpath)) {
|
|
delete_error = true;
|
|
status = F("Cannot deleted ") ;
|
|
status+=fullpath;
|
|
}
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
file2deleted = dir.openNextFile();
|
|
#endif
|
|
}
|
|
}
|
|
if (!delete_error) {
|
|
status = shortname ;
|
|
status+=" deleted";
|
|
}
|
|
}
|
|
}
|
|
//create a directory
|
|
if(web_interface->web_server.arg("action")=="createdir" && web_interface->web_server.hasArg("filename")) {
|
|
String filename;
|
|
filename = path + web_interface->web_server.arg("filename") +"/.";
|
|
String shortname = web_interface->web_server.arg("filename");
|
|
shortname.replace("/","");
|
|
filename.replace("//","/");
|
|
if(SPIFFS.exists(filename)) {
|
|
status = shortname + F(" already exists!");
|
|
} else {
|
|
FS_FILE r = SPIFFS.open(filename,SPIFFS_FILE_WRITE);
|
|
if (!r) {
|
|
status = F("Cannot create ");
|
|
status += shortname ;
|
|
} else {
|
|
r.close();
|
|
status = shortname + F(" created");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
String jsonfile = "{";
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
FS_DIR dir = SPIFFS.openDir(path);
|
|
#else
|
|
String ptmp = path;
|
|
if ((path != "/") && (path[path.length()-1]='/'))ptmp = path.substring(0,path.length()-1);
|
|
FS_FILE dir = SPIFFS.open(ptmp);
|
|
#endif
|
|
jsonfile+="\"files\":[";
|
|
bool firstentry=true;
|
|
String subdirlist="";
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
while (dir.next()) {
|
|
String filename = dir.fileName();
|
|
#else
|
|
File fileparsed = dir.openNextFile();
|
|
while (fileparsed) {
|
|
String filename = fileparsed.name();
|
|
#endif
|
|
String size ="";
|
|
bool addtolist=true;
|
|
//remove path from name
|
|
filename = filename.substring(path.length(),filename.length());
|
|
//check if file or subfile
|
|
if (filename.indexOf("/")>-1) {
|
|
//Do not rely on "/." to define directory as SPIFFS upload won't create it but directly files
|
|
//and no need to overload SPIFFS if not necessary to create "/." if no need
|
|
//it will reduce SPIFFS available space so limit it to creation
|
|
filename = filename.substring(0,filename.indexOf("/"));
|
|
String tag="*";
|
|
tag += filename + "*";
|
|
if (subdirlist.indexOf(tag)>-1 || filename.length()==0) { //already in list
|
|
addtolist = false; //no need to add
|
|
} else {
|
|
size = -1; //it is subfile so display only directory, size will be -1 to describe it is directory
|
|
if (subdirlist.length()==0) {
|
|
subdirlist+="*";
|
|
}
|
|
subdirlist += filename + "*"; //add to list
|
|
}
|
|
} else {
|
|
//do not add "." file
|
|
if (!((filename==".") || (filename==""))) {
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
size = CONFIG::formatBytes(dir.fileSize());
|
|
#else
|
|
size = CONFIG::formatBytes(fileparsed.size());
|
|
#endif
|
|
|
|
} else {
|
|
addtolist = false;
|
|
}
|
|
}
|
|
if(addtolist) {
|
|
if (!firstentry) {
|
|
jsonfile+=",";
|
|
} else {
|
|
firstentry=false;
|
|
}
|
|
jsonfile+="{";
|
|
jsonfile+="\"name\":\"";
|
|
jsonfile+=filename;
|
|
jsonfile+="\",\"size\":\"";
|
|
jsonfile+=size;
|
|
jsonfile+="\"";
|
|
jsonfile+="}";
|
|
}
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
fileparsed = dir.openNextFile();
|
|
#endif
|
|
}
|
|
jsonfile+="],";
|
|
jsonfile+="\"path\":\"" + path + "\",";
|
|
jsonfile+="\"status\":\"" + status + "\",";
|
|
size_t totalBytes;
|
|
size_t usedBytes;
|
|
#ifdef ARDUINO_ARCH_ESP8266
|
|
fs::FSInfo info;
|
|
SPIFFS.info(info);
|
|
totalBytes = info.totalBytes;
|
|
usedBytes = info.usedBytes;
|
|
#else
|
|
totalBytes = SPIFFS.totalBytes();
|
|
usedBytes = SPIFFS.usedBytes();
|
|
#endif
|
|
jsonfile+="\"total\":\"" + CONFIG::formatBytes(totalBytes) + "\",";
|
|
jsonfile+="\"used\":\"" + CONFIG::formatBytes(usedBytes) + "\",";
|
|
jsonfile.concat(F("\"occupation\":\""));
|
|
jsonfile+= CONFIG::intTostr(100*usedBytes/totalBytes);
|
|
jsonfile+="\"";
|
|
jsonfile+="}";
|
|
path = "";
|
|
web_interface->web_server.sendHeader("Cache-Control", "no-cache");
|
|
web_interface->web_server.send(200, "application/json", jsonfile);
|
|
web_interface->_upload_status=UPLOAD_STATUS_NONE;
|
|
}
|
|
|
|
//serial SD files list
|
|
void handle_serial_SDFileList()
|
|
{
|
|
//this is only for admin an user
|
|
if (web_interface->is_authenticated() == LEVEL_GUEST) {
|
|
web_interface->_upload_status=UPLOAD_STATUS_NONE;
|
|
web_interface->web_server.sendHeader("Cache-Control", "no-cache");
|
|
web_interface->web_server.send(401, "application/json", "{\"status\":\"Authentication failed!\"}");
|
|
return;
|
|
}
|
|
LOG("serial SD upload done\r\n")
|
|
String sstatus="Ok";
|
|
if ((web_interface->_upload_status == UPLOAD_STATUS_FAILED) || (web_interface->_upload_status == UPLOAD_STATUS_CANCELLED)) {
|
|
sstatus = "Upload failed";
|
|
web_interface->_upload_status = UPLOAD_STATUS_NONE;
|
|
}
|
|
String jsonfile = "{\"status\":\"" + sstatus + "\"}";
|
|
web_interface->web_server.sendHeader("Cache-Control", "no-cache");
|
|
web_interface->web_server.send(200, "application/json", jsonfile);
|
|
web_interface->blockserial = false;
|
|
web_interface->_upload_status=UPLOAD_STATUS_NONE;
|
|
}
|
|
|
|
|
|
//do a redirect to avoid to many query
|
|
//and handle not registred path
|
|
void handle_not_found()
|
|
{
|
|
static const char NOT_AUTH_NF [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /\r\nCache-Control: no-cache\r\n\r\n";
|
|
|
|
if (web_interface->is_authenticated() == LEVEL_GUEST) {
|
|
web_interface->web_server.sendContent_P(NOT_AUTH_NF);
|
|
//web_interface->web_server.client().stop();
|
|
return;
|
|
}
|
|
bool page_not_found = false;
|
|
String path = web_interface->web_server.urlDecode(web_interface->web_server.uri());
|
|
String contentType = web_interface->getContentType(path);
|
|
String pathWithGz = path + ".gz";
|
|
LOG("request:")
|
|
LOG(path)
|
|
LOG("\r\n")
|
|
#ifdef DEBUG_ESP3D
|
|
int nb = web_interface->web_server.args();
|
|
for (int i = 0 ; i < nb; i++) {
|
|
LOG(web_interface->web_server.argName(i))
|
|
LOG(":")
|
|
LOG(web_interface->web_server.arg(i))
|
|
LOG("\r\n")
|
|
|
|
}
|
|
#endif
|
|
LOG("type:")
|
|
LOG(contentType)
|
|
LOG("\r\n")
|
|
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) {
|
|
if(SPIFFS.exists(pathWithGz)) {
|
|
path = pathWithGz;
|
|
}
|
|
FS_FILE file = SPIFFS.open(path, SPIFFS_FILE_READ);
|
|
web_interface->web_server.streamFile(file, contentType);
|
|
file.close();
|
|
return;
|
|
} else {
|
|
page_not_found = true;
|
|
}
|
|
|
|
if (page_not_found ) {
|
|
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
if (WiFi.getMode()!=WIFI_STA ) {
|
|
String contentType=FPSTR(PAGE_CAPTIVE);
|
|
String stmp = WiFi.softAPIP().toString();
|
|
//Web address = ip + port
|
|
String KEY_IP = F("$WEB_ADDRESS$");
|
|
String KEY_QUERY = F("$QUERY$");
|
|
if (wifi_config.iweb_port!=80) {
|
|
stmp+=":";
|
|
stmp+=CONFIG::intTostr(wifi_config.iweb_port);
|
|
}
|
|
contentType.replace(KEY_IP,stmp);
|
|
contentType.replace(KEY_IP,stmp);
|
|
contentType.replace(KEY_QUERY,web_interface->web_server.uri());
|
|
web_interface->web_server.send(200,"text/html",contentType);
|
|
//web_interface->web_server.sendContent_P(NOT_AUTH_NF);
|
|
//web_interface->web_server.client().stop();
|
|
return;
|
|
}
|
|
#endif
|
|
LOG("Page not found\r\n")
|
|
path = F("/404.htm");
|
|
contentType = web_interface->getContentType(path);
|
|
pathWithGz = path + F(".gz");
|
|
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) {
|
|
if(SPIFFS.exists(pathWithGz)) {
|
|
path = pathWithGz;
|
|
}
|
|
FS_FILE file = SPIFFS.open(path, SPIFFS_FILE_READ);
|
|
web_interface->web_server.streamFile(file, contentType);
|
|
file.close();
|
|
|
|
} else {
|
|
//if not template use default page
|
|
contentType=FPSTR(PAGE_404);
|
|
String stmp;
|
|
if (WiFi.getMode()==WIFI_STA ) {
|
|
stmp=WiFi.localIP().toString();
|
|
} else {
|
|
stmp=WiFi.softAPIP().toString();
|
|
}
|
|
//Web address = ip + port
|
|
String KEY_IP = F("$WEB_ADDRESS$");
|
|
String KEY_QUERY = F("$QUERY$");
|
|
if (wifi_config.iweb_port!=80) {
|
|
stmp+=":";
|
|
stmp+=CONFIG::intTostr(wifi_config.iweb_port);
|
|
}
|
|
contentType.replace(KEY_IP,stmp);
|
|
contentType.replace(KEY_QUERY,web_interface->web_server.uri());
|
|
web_interface->web_server.send(200,"text/html",contentType);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef AUTHENTICATION_FEATURE
|
|
void handle_login()
|
|
{
|
|
String smsg;
|
|
String sUser,sPassword;
|
|
String auths;
|
|
int code = 200;
|
|
bool msg_alert_error=false;
|
|
//disconnect can be done anytime no need to check credential
|
|
if (web_interface->web_server.hasArg("DISCONNECT")) {
|
|
String cookie = web_interface->web_server.header("Cookie");
|
|
int pos = cookie.indexOf("ESPSESSIONID=");
|
|
String sessionID;
|
|
if (pos!= -1) {
|
|
int pos2 = cookie.indexOf(";",pos);
|
|
sessionID = cookie.substring(pos+strlen("ESPSESSIONID="),pos2);
|
|
}
|
|
web_interface->ClearAuthIP(web_interface->web_server.client().remoteIP(), sessionID.c_str());
|
|
web_interface->web_server.sendHeader("Set-Cookie","ESPSESSIONID=0");
|
|
web_interface->web_server.sendHeader("Cache-Control","no-cache");
|
|
String buffer2send = "{\"status\":\"Ok\",\"authentication_lvl\":\"guest\"}";
|
|
web_interface->web_server.send(code, "application/json", buffer2send);
|
|
//web_interface->web_server.client().stop();
|
|
return;
|
|
}
|
|
|
|
level_authenticate_type auth_level= web_interface->is_authenticated();
|
|
if (auth_level == LEVEL_GUEST) auths = F("guest");
|
|
else if (auth_level == LEVEL_USER) auths = F("user");
|
|
else if (auth_level == LEVEL_ADMIN) auths = F("admin");
|
|
else auths = F("???");
|
|
|
|
//check is it is a submission or a query
|
|
if (web_interface->web_server.hasArg("SUBMIT")) {
|
|
//is there a correct list of query?
|
|
if ( web_interface->web_server.hasArg("PASSWORD")&& web_interface->web_server.hasArg("USER")) {
|
|
//USER
|
|
sUser = web_interface->web_server.arg("USER");
|
|
if ( !((sUser==FPSTR(DEFAULT_ADMIN_LOGIN)) || (sUser==FPSTR(DEFAULT_USER_LOGIN)))) {
|
|
msg_alert_error=true;
|
|
smsg=F("Error : Incorrect User");
|
|
code=401;
|
|
}
|
|
if (msg_alert_error == false) {
|
|
//Password
|
|
sPassword = web_interface->web_server.arg("PASSWORD");
|
|
String sadminPassword;
|
|
|
|
if (!CONFIG::read_string(EP_ADMIN_PWD, sadminPassword, MAX_LOCAL_PASSWORD_LENGTH)) {
|
|
sadminPassword=FPSTR(DEFAULT_ADMIN_PWD);
|
|
}
|
|
|
|
String suserPassword;
|
|
|
|
if (!CONFIG::read_string(EP_USER_PWD, suserPassword, MAX_LOCAL_PASSWORD_LENGTH)) {
|
|
suserPassword=FPSTR(DEFAULT_USER_PWD);
|
|
}
|
|
|
|
if(!(((sUser==FPSTR(DEFAULT_ADMIN_LOGIN)) && (strcmp(sPassword.c_str(),sadminPassword.c_str())==0)) ||
|
|
((sUser==FPSTR(DEFAULT_USER_LOGIN)) && (strcmp(sPassword.c_str(),suserPassword.c_str()) == 0)))) {
|
|
msg_alert_error=true;
|
|
smsg=F("Error: Incorrect password");
|
|
code = 401;
|
|
}
|
|
}
|
|
} else {
|
|
msg_alert_error=true;
|
|
smsg = F("Error: Missing data");
|
|
code = 500;
|
|
}
|
|
//change password
|
|
if ( web_interface->web_server.hasArg("PASSWORD")&& web_interface->web_server.hasArg("USER") && web_interface->web_server.hasArg("NEWPASSWORD") && (msg_alert_error==false) ) {
|
|
String newpassword = web_interface->web_server.arg("NEWPASSWORD");
|
|
if (CONFIG::isLocalPasswordValid(newpassword.c_str())) {
|
|
int pos=0;
|
|
if(sUser==FPSTR(DEFAULT_ADMIN_LOGIN)) pos = EP_ADMIN_PWD;
|
|
else pos = EP_USER_PWD;
|
|
if (!CONFIG::write_string(pos,newpassword.c_str())){
|
|
msg_alert_error=true;
|
|
smsg = F("Error: Cannot apply changes");
|
|
code = 500;
|
|
}
|
|
} else {
|
|
msg_alert_error=true;
|
|
smsg = F("Error: Incorrect password");
|
|
code = 500;
|
|
}
|
|
}
|
|
if ((code == 200) || (code == 500)) {
|
|
level_authenticate_type current_auth_level;
|
|
if(sUser == FPSTR(DEFAULT_ADMIN_LOGIN)) {
|
|
current_auth_level = LEVEL_ADMIN;
|
|
} else if(sUser == FPSTR(DEFAULT_USER_LOGIN)){
|
|
current_auth_level = LEVEL_USER;
|
|
} else {
|
|
current_auth_level = LEVEL_GUEST;
|
|
}
|
|
//create Session
|
|
if ((current_auth_level != auth_level) || (auth_level== LEVEL_GUEST)) {
|
|
auth_ip * current_auth = new auth_ip;
|
|
current_auth->level = current_auth_level;
|
|
current_auth->ip=web_interface->web_server.client().remoteIP();
|
|
strcpy(current_auth->sessionID,web_interface->create_session_ID());
|
|
strcpy(current_auth->userID,sUser.c_str());
|
|
current_auth->last_time=millis();
|
|
if (web_interface->AddAuthIP(current_auth)) {
|
|
String tmps ="ESPSESSIONID=";
|
|
tmps+=current_auth->sessionID;
|
|
web_interface->web_server.sendHeader("Set-Cookie",tmps);
|
|
web_interface->web_server.sendHeader("Cache-Control","no-cache");
|
|
switch(current_auth->level) {
|
|
case LEVEL_ADMIN:
|
|
auths = "admin";
|
|
break;
|
|
case LEVEL_USER:
|
|
auths = "user";
|
|
break;
|
|
default:
|
|
auths = "guest";
|
|
}
|
|
} else {
|
|
delete current_auth;
|
|
msg_alert_error=true;
|
|
code = 500;
|
|
smsg = F("Error: Too many connections");
|
|
}
|
|
}
|
|
}
|
|
if (code == 200) smsg = F("Ok");
|
|
|
|
//build JSON
|
|
String buffer2send = "{\"status\":\"" + smsg + "\",\"authentication_lvl\":\"";
|
|
buffer2send += auths;
|
|
buffer2send += "\"}";
|
|
web_interface->web_server.send(code, "application/json", buffer2send);
|
|
} else {
|
|
if (auth_level != LEVEL_GUEST) {
|
|
String cookie = web_interface->web_server.header("Cookie");
|
|
int pos = cookie.indexOf("ESPSESSIONID=");
|
|
String sessionID;
|
|
if (pos!= -1) {
|
|
int pos2 = cookie.indexOf(";",pos);
|
|
sessionID = cookie.substring(pos+strlen("ESPSESSIONID="),pos2);
|
|
auth_ip * current_auth_info = web_interface->GetAuth(web_interface->web_server.client().remoteIP(), sessionID.c_str());
|
|
if (current_auth_info != NULL){
|
|
sUser = current_auth_info->userID;
|
|
}
|
|
}
|
|
}
|
|
String buffer2send = "{\"status\":\"200\",\"authentication_lvl\":\"";
|
|
buffer2send += auths;
|
|
buffer2send += "\",\"user\":\"";
|
|
buffer2send += sUser;
|
|
buffer2send +="\"}";
|
|
web_interface->web_server.send(code, "application/json", buffer2send);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
//Handle web command query and send answer
|
|
void handle_web_command()
|
|
{
|
|
level_authenticate_type auth_level= web_interface->is_authenticated();
|
|
/* if (auth_level == LEVEL_GUEST) {
|
|
web_interface->web_server.send(403,"text/plain","Not allowed, log in first!\n");
|
|
return;
|
|
}*/
|
|
String buffer2send = "";
|
|
LOG(String (web_interface->web_server.args()))
|
|
LOG(" Web command\r\n")
|
|
#ifdef DEBUG_ESP3D
|
|
int nb = web_interface->web_server.args();
|
|
for (int i = 0 ; i < nb; i++) {
|
|
LOG(web_interface->web_server.argName(i))
|
|
LOG(":")
|
|
LOG(web_interface->web_server.arg(i))
|
|
LOG("\r\n")
|
|
}
|
|
#endif
|
|
String cmd = "";
|
|
int count ;
|
|
if (web_interface->web_server.hasArg("plain") || web_interface->web_server.hasArg("commandText")) {
|
|
if (web_interface->web_server.hasArg("plain")) {
|
|
cmd = web_interface->web_server.arg("plain");
|
|
} else {
|
|
cmd = web_interface->web_server.arg("commandText");
|
|
}
|
|
LOG("Web Command:")
|
|
LOG(cmd)
|
|
LOG("\r\n")
|
|
} else {
|
|
LOG("invalid argument\r\n")
|
|
web_interface->web_server.send(200,"text/plain","Invalid command");
|
|
return;
|
|
}
|
|
//if it is for ESP module [ESPXXX]<parameter>
|
|
cmd.trim();
|
|
int ESPpos = cmd.indexOf("[ESP");
|
|
if (ESPpos>-1) {
|
|
//is there the second part?
|
|
int ESPpos2 = cmd.indexOf("]",ESPpos);
|
|
if (ESPpos2>-1) {
|
|
//Split in command and parameters
|
|
String cmd_part1=cmd.substring(ESPpos+4,ESPpos2);
|
|
String cmd_part2="";
|
|
//only [ESP800] is allowed login free if authentication is enabled
|
|
if ((auth_level == LEVEL_GUEST) && (cmd_part1.toInt()!=800)) {
|
|
web_interface->web_server.send(401,"text/plain","Authentication failed!\n");
|
|
return;
|
|
}
|
|
//is there space for parameters?
|
|
if (ESPpos2<cmd.length()) {
|
|
cmd_part2=cmd.substring(ESPpos2+1);
|
|
}
|
|
//if command is a valid number then execute command
|
|
if(cmd_part1.toInt()!=0) {
|
|
COMMAND::execute_command(cmd_part1.toInt(), cmd_part2, WEB_PIPE, auth_level);
|
|
BRIDGE::flush(WEB_PIPE);
|
|
}
|
|
//if not is not a valid [ESPXXX] command
|
|
}
|
|
} else {
|
|
if (auth_level == LEVEL_GUEST) {
|
|
web_interface->web_server.send(401,"text/plain","Authentication failed!\n");
|
|
return;
|
|
}
|
|
//send command to serial as no need to transfer ESP command
|
|
//to avoid any pollution if Uploading file to SDCard
|
|
if ((web_interface->blockserial) == false) {
|
|
//block every query
|
|
web_interface->blockserial = true;
|
|
LOG("Block Serial\r\n")
|
|
//empty the serial buffer and incoming data
|
|
LOG("Start PurgeSerial\r\n")
|
|
if(ESP_SERIAL_OUT.available()) {
|
|
BRIDGE::processFromSerial2TCP();
|
|
delay(1);
|
|
}
|
|
LOG("End PurgeSerial\r\n")
|
|
web_interface->web_server.setContentLength(CONTENT_LENGTH_UNKNOWN);
|
|
web_interface->web_server.sendHeader("Content-Type","text/plain",true);
|
|
web_interface->web_server.sendHeader("Cache-Control","no-cache");
|
|
web_interface->web_server.send(200);
|
|
//send command
|
|
LOG(String(cmd.length()))
|
|
LOG("Start PurgeSerial\r\n")
|
|
if(ESP_SERIAL_OUT.available()) {
|
|
BRIDGE::processFromSerial2TCP();
|
|
delay(1);
|
|
}
|
|
LOG("End PurgeSerial\r\n")
|
|
LOG("Send Command\r\n")
|
|
ESP_SERIAL_OUT.println(cmd);
|
|
count = 0;
|
|
String current_buffer;
|
|
String current_line;
|
|
//int pos;
|
|
int temp_counter = 0;
|
|
String tmp;
|
|
bool datasent = false;
|
|
//pickup the list
|
|
while (count < MAX_TRY) {
|
|
//give some time between each buffer
|
|
if (ESP_SERIAL_OUT.available()) {
|
|
count = 0;
|
|
size_t len = ESP_SERIAL_OUT.available();
|
|
uint8_t sbuf[len+1];
|
|
//read buffer
|
|
ESP_SERIAL_OUT.readBytes(sbuf, len);
|
|
//change buffer as string
|
|
sbuf[len]='\0';
|
|
//add buffer to current one if any
|
|
current_buffer += (char * ) sbuf;
|
|
while (current_buffer.indexOf("\n") !=-1) {
|
|
//remove the possible "\r"
|
|
current_buffer.replace("\r","");
|
|
//pos = current_buffer.indexOf("\n");
|
|
//get line
|
|
current_line = current_buffer.substring(0,current_buffer.indexOf("\n"));
|
|
//if line is command ack - just exit so save the time out period
|
|
if ((current_line == "ok") || (current_line == "wait")) {
|
|
count = MAX_TRY;
|
|
LOG("Found ok\r\n")
|
|
break;
|
|
}
|
|
//get the line and transmit it
|
|
LOG("Check command: ")
|
|
LOG(current_line)
|
|
LOG("\r\n")
|
|
//check command
|
|
if ((CONFIG::GetFirmwareTarget() == REPETIER) || (CONFIG::GetFirmwareTarget() == REPETIER4DV)){
|
|
//save time no need to continue
|
|
if (current_line.indexOf("busy:") > -1) {
|
|
temp_counter++;
|
|
} else if (COMMAND::check_command(current_line, NO_PIPE, false)) {
|
|
temp_counter ++ ;
|
|
}
|
|
}else {
|
|
if (COMMAND::check_command(current_line, NO_PIPE, false)) {
|
|
temp_counter ++ ;
|
|
}
|
|
}
|
|
if (temp_counter > 5) {
|
|
break;
|
|
}
|
|
if ((CONFIG::GetFirmwareTarget() == REPETIER) || (CONFIG::GetFirmwareTarget() == REPETIER4DV)) {
|
|
if (!current_line.startsWith( "ok "))
|
|
{
|
|
buffer2send +=current_line;
|
|
buffer2send +="\n";
|
|
}
|
|
} else {
|
|
buffer2send +=current_line;
|
|
buffer2send +="\n";
|
|
}
|
|
if (buffer2send.length() > 1200) {
|
|
web_interface->web_server.sendContent(buffer2send);
|
|
buffer2send = "";
|
|
datasent = true;
|
|
}
|
|
//current remove line from buffer
|
|
tmp = current_buffer.substring(current_buffer.indexOf("\n")+1,current_buffer.length());
|
|
current_buffer = tmp;
|
|
delay(0);
|
|
}
|
|
delay (0);
|
|
} else {
|
|
delay(1);
|
|
}
|
|
//it is sending too many temp status should be heating so let's exit the loop
|
|
if (temp_counter > 5) {
|
|
count = MAX_TRY;
|
|
}
|
|
count++;
|
|
}
|
|
//to be sure connection close
|
|
if (buffer2send.length() > 0) {
|
|
web_interface->web_server.sendContent(buffer2send);
|
|
datasent = true;
|
|
}
|
|
if (!datasent) {
|
|
web_interface->web_server.sendContent(" \r\n");
|
|
}
|
|
web_interface->web_server.sendContent("");
|
|
LOG("Start PurgeSerial\r\n")
|
|
if(ESP_SERIAL_OUT.available()) {
|
|
BRIDGE::processFromSerial2TCP();
|
|
delay(1);
|
|
}
|
|
LOG("End PurgeSerial\r\n")
|
|
web_interface->blockserial = false;
|
|
LOG("Release Serial\r\n")
|
|
} else {
|
|
web_interface->web_server.send(200,"text/plain","Serial is busy, retry later!");
|
|
}
|
|
}
|
|
}
|
|
|
|
//Handle web command query and sent ack or fail instead of answer
|
|
void handle_web_command_silent()
|
|
{
|
|
level_authenticate_type auth_level= web_interface->is_authenticated();
|
|
if (auth_level == LEVEL_GUEST) {
|
|
web_interface->web_server.send(401,"text/plain","Authentication failed!\n");
|
|
return;
|
|
}
|
|
String buffer2send = "";
|
|
LOG(String (web_interface->web_server.args()))
|
|
LOG(" Web silent command\r\n")
|
|
#ifdef DEBUG_ESP3D
|
|
int nb = web_interface->web_server.args();
|
|
for (int i = 0 ; i < nb; i++) {
|
|
LOG(web_interface->web_server.argName(i))
|
|
LOG(":")
|
|
LOG(web_interface->web_server.arg(i))
|
|
LOG("\r\n")
|
|
}
|
|
#endif
|
|
String cmd = "";
|
|
//int count ;
|
|
if (web_interface->web_server.hasArg("plain") || web_interface->web_server.hasArg("commandText")) {
|
|
if (web_interface->web_server.hasArg("plain")) {
|
|
cmd = web_interface->web_server.arg("plain");
|
|
} else {
|
|
cmd = web_interface->web_server.arg("commandText");
|
|
}
|
|
LOG("Web Command:")
|
|
LOG(cmd)
|
|
LOG("\r\n")
|
|
} else {
|
|
LOG("invalid argument\r\n")
|
|
web_interface->web_server.send(200,"text/plain","Invalid command");
|
|
return;
|
|
}
|
|
//if it is for ESP module [ESPXXX]<parameter>
|
|
cmd.trim();
|
|
int ESPpos = cmd.indexOf("[ESP");
|
|
if (ESPpos>-1) {
|
|
//is there the second part?
|
|
int ESPpos2 = cmd.indexOf("]",ESPpos);
|
|
if (ESPpos2>-1) {
|
|
//Split in command and parameters
|
|
String cmd_part1=cmd.substring(ESPpos+4,ESPpos2);
|
|
String cmd_part2="";
|
|
//is there space for parameters?
|
|
if (ESPpos2<cmd.length()) {
|
|
cmd_part2=cmd.substring(ESPpos2+1);
|
|
}
|
|
//if command is a valid number then execute command
|
|
if(cmd_part1.toInt()!=0) {
|
|
if (COMMAND::execute_command(cmd_part1.toInt(),cmd_part2,NO_PIPE, auth_level)) {
|
|
web_interface->web_server.send(200,"text/plain","ok");
|
|
} else {
|
|
web_interface->web_server.send(500,"text/plain","error");
|
|
}
|
|
|
|
}
|
|
//if not is not a valid [ESPXXX] command
|
|
}
|
|
} else {
|
|
//send command to serial as no need to transfer ESP command
|
|
//to avoid any pollution if Uploading file to SDCard
|
|
if ((web_interface->blockserial) == false) {
|
|
LOG("Send Command\r\n")
|
|
//send command
|
|
ESP_SERIAL_OUT.println(cmd);
|
|
web_interface->web_server.send(200,"text/plain","ok");
|
|
} else {
|
|
web_interface->web_server.send(200,"text/plain","Serial is busy, retry later!");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef SSDP_FEATURE
|
|
void handle_SSDP()
|
|
{
|
|
SSDP.schema(web_interface->web_server.client());
|
|
}
|
|
#endif
|
|
|
|
//constructor
|
|
WEBINTERFACE_CLASS::WEBINTERFACE_CLASS (int port):web_server(port)
|
|
{
|
|
//init what will handle "/"
|
|
web_server.on("/",HTTP_ANY, handle_web_interface_root);
|
|
web_server.on("/command",HTTP_ANY, handle_web_command);
|
|
web_server.on("/command_silent",HTTP_ANY, handle_web_command_silent);
|
|
web_server.on("/upload_serial", HTTP_ANY, handle_serial_SDFileList,SDFile_serial_upload);
|
|
web_server.on("/files", HTTP_ANY, handleFileList,SPIFFSFileupload);
|
|
#ifdef WEB_UPDATE_FEATURE
|
|
web_server.on("/updatefw",HTTP_ANY, handleUpdate,WebUpdateUpload);
|
|
#endif
|
|
#ifdef AUTHENTICATION_FEATURE
|
|
web_server.on("/login", HTTP_ANY, handle_login);
|
|
#endif
|
|
//TODO: to be reviewed
|
|
web_server.on("/STATUS",HTTP_ANY, handle_web_interface_status);
|
|
#ifdef SSDP_FEATURE
|
|
web_server.on("/description.xml", HTTP_GET, handle_SSDP);
|
|
#endif
|
|
#ifdef CAPTIVE_PORTAL_FEATURE
|
|
web_server.on("/generate_204",HTTP_ANY, handle_web_interface_root);
|
|
web_server.on("/gconnectivitycheck.gstatic.com",HTTP_ANY, handle_web_interface_root);
|
|
//do not forget the / at the end
|
|
web_server.on("/fwlink/",HTTP_ANY, handle_web_interface_root);
|
|
#endif
|
|
web_server.onNotFound( handle_not_found);
|
|
blockserial = false;
|
|
restartmodule=false;
|
|
//rolling list of 4entries with a maximum of 50 char for each entry
|
|
#ifdef ERROR_MSG_FEATURE
|
|
error_msg.setsize(4);
|
|
error_msg.setlength(50);
|
|
#endif
|
|
#ifdef INFO_MSG_FEATURE
|
|
info_msg.setsize(4);
|
|
info_msg.setlength(50);
|
|
#endif
|
|
#ifdef STATUS_MSG_FEATURE
|
|
status_msg.setsize(4);
|
|
status_msg.setlength(50);
|
|
#endif
|
|
fsUploadFile=(FS_FILE)0;
|
|
_head=NULL;
|
|
_nb_ip=0;
|
|
_upload_status=UPLOAD_STATUS_NONE;
|
|
}
|
|
//Destructor
|
|
WEBINTERFACE_CLASS::~WEBINTERFACE_CLASS()
|
|
{
|
|
#ifdef INFO_MSG_FEATURE
|
|
info_msg.clear();
|
|
#endif
|
|
#ifdef ERROR_MSG_FEATURE
|
|
error_msg.clear();
|
|
#endif
|
|
#ifdef STATUS_MSG_FEATURE
|
|
status_msg.clear();
|
|
#endif
|
|
while (_head) {
|
|
auth_ip * current = _head;
|
|
_head=_head->_next;
|
|
delete current;
|
|
}
|
|
_nb_ip=0;
|
|
}
|
|
//check authentification
|
|
level_authenticate_type WEBINTERFACE_CLASS::is_authenticated()
|
|
{
|
|
#ifdef AUTHENTICATION_FEATURE
|
|
if (web_server.hasHeader("Cookie")) {
|
|
String cookie = web_server.header("Cookie");
|
|
int pos = cookie.indexOf("ESPSESSIONID=");
|
|
if (pos!= -1) {
|
|
int pos2 = cookie.indexOf(";",pos);
|
|
String sessionID = cookie.substring(pos+strlen("ESPSESSIONID="),pos2);
|
|
IPAddress ip = web_server.client().remoteIP();
|
|
//check if cookie can be reset and clean table in same time
|
|
return ResetAuthIP(ip,sessionID.c_str());
|
|
}
|
|
}
|
|
return LEVEL_GUEST;
|
|
#else
|
|
return LEVEL_ADMIN;
|
|
#endif
|
|
}
|
|
|
|
#ifdef AUTHENTICATION_FEATURE
|
|
//add the information in the linked list if possible
|
|
bool WEBINTERFACE_CLASS::AddAuthIP(auth_ip * item)
|
|
{
|
|
if (_nb_ip>MAX_AUTH_IP) {
|
|
return false;
|
|
}
|
|
item->_next=_head;
|
|
_head=item;
|
|
_nb_ip++;
|
|
return true;
|
|
}
|
|
|
|
//Session ID based on IP and time using 16 char
|
|
char * WEBINTERFACE_CLASS::create_session_ID()
|
|
{
|
|
static char sessionID[17];
|
|
//reset SESSIONID
|
|
for (int i=0; i<17; i++) {
|
|
sessionID[i]='\0';
|
|
}
|
|
//get time
|
|
uint32_t now = millis();
|
|
//get remote IP
|
|
IPAddress remoteIP=web_server.client().remoteIP();
|
|
//generate SESSIONID
|
|
if (0>sprintf(sessionID,"%02X%02X%02X%02X%02X%02X%02X%02X",remoteIP[0],remoteIP[1],remoteIP[2],remoteIP[3],(uint8_t) ((now >> 0) & 0xff),(uint8_t) ((now >> 8) & 0xff),(uint8_t) ((now >> 16) & 0xff),(uint8_t) ((now >> 24) & 0xff))) {
|
|
strcpy(sessionID,"NONE");
|
|
}
|
|
return sessionID;
|
|
}
|
|
|
|
|
|
|
|
bool WEBINTERFACE_CLASS::ClearAuthIP(IPAddress ip, const char * sessionID){
|
|
auth_ip * current = _head;
|
|
auth_ip * previous = NULL;
|
|
bool done = false;
|
|
while (current) {
|
|
if ((ip == current->ip) && (strcmp(sessionID,current->sessionID)==0)) {
|
|
//remove
|
|
done = true;
|
|
if (current ==_head) {
|
|
_head=current->_next;
|
|
_nb_ip--;
|
|
delete current;
|
|
current=_head;
|
|
} else {
|
|
previous->_next=current->_next;
|
|
_nb_ip--;
|
|
delete current;
|
|
current=previous->_next;
|
|
}
|
|
} else {
|
|
previous = current;
|
|
current=current->_next;
|
|
}
|
|
}
|
|
return done;
|
|
}
|
|
|
|
//Get info
|
|
auth_ip * WEBINTERFACE_CLASS::GetAuth(IPAddress ip,const char * sessionID)
|
|
{
|
|
auth_ip * current = _head;
|
|
auth_ip * previous = NULL;
|
|
//get time
|
|
//uint32_t now = millis();
|
|
while (current) {
|
|
if (ip==current->ip) {
|
|
if (strcmp(sessionID,current->sessionID)==0) {
|
|
//found
|
|
return current;
|
|
}
|
|
}
|
|
previous = current;
|
|
current=current->_next;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//Review all IP to reset timers
|
|
level_authenticate_type WEBINTERFACE_CLASS::ResetAuthIP(IPAddress ip,const char * sessionID)
|
|
{
|
|
auth_ip * current = _head;
|
|
auth_ip * previous = NULL;
|
|
//get time
|
|
//uint32_t now = millis();
|
|
while (current) {
|
|
if ((millis()-current->last_time)>180000) {
|
|
//remove
|
|
if (current==_head) {
|
|
_head=current->_next;
|
|
_nb_ip--;
|
|
delete current;
|
|
current=_head;
|
|
} else {
|
|
previous->_next=current->_next;
|
|
_nb_ip--;
|
|
delete current;
|
|
current=previous->_next;
|
|
}
|
|
} else {
|
|
if (ip==current->ip) {
|
|
if (strcmp(sessionID,current->sessionID)==0) {
|
|
//reset time
|
|
current->last_time=millis();
|
|
return (level_authenticate_type)current->level;
|
|
}
|
|
}
|
|
previous = current;
|
|
current=current->_next;
|
|
}
|
|
}
|
|
return LEVEL_GUEST;
|
|
}
|
|
#endif
|
|
|
|
//Check what is the content tye according extension file
|
|
String WEBINTERFACE_CLASS::getContentType(String filename)
|
|
{
|
|
if(filename.endsWith(".htm")) {
|
|
return "text/html";
|
|
} else if(filename.endsWith(".html")) {
|
|
return "text/html";
|
|
} else if(filename.endsWith(".css")) {
|
|
return "text/css";
|
|
} else if(filename.endsWith(".js")) {
|
|
return "application/javascript";
|
|
} else if(filename.endsWith(".png")) {
|
|
return "image/png";
|
|
} else if(filename.endsWith(".gif")) {
|
|
return "image/gif";
|
|
} else if(filename.endsWith(".jpeg")) {
|
|
return "image/jpeg";
|
|
} else if(filename.endsWith(".jpg")) {
|
|
return "image/jpeg";
|
|
} else if(filename.endsWith(".ico")) {
|
|
return "image/x-icon";
|
|
} else if(filename.endsWith(".xml")) {
|
|
return "text/xml";
|
|
} else if(filename.endsWith(".pdf")) {
|
|
return "application/x-pdf";
|
|
} else if(filename.endsWith(".zip")) {
|
|
return "application/x-zip";
|
|
} else if(filename.endsWith(".gz")) {
|
|
return "application/x-gzip";
|
|
} else if(filename.endsWith(".tpl")) {
|
|
return "text/plain";
|
|
} else if(filename.endsWith(".inc")) {
|
|
return "text/plain";
|
|
} else if(filename.endsWith(".txt")) {
|
|
return "text/plain";
|
|
}
|
|
return "application/octet-stream";
|
|
}
|
|
|
|
|
|
WEBINTERFACE_CLASS * web_interface;
|