sforkowany z mirror/meshtastic-firmware
Set web cookie and web text editor.
rodzic
bea00569fd
commit
951b4293c4
|
@ -54,6 +54,7 @@ void handleHotspot(HTTPRequest *req, HTTPResponse *res);
|
||||||
void handleFavicon(HTTPRequest *req, HTTPResponse *res);
|
void handleFavicon(HTTPRequest *req, HTTPResponse *res);
|
||||||
void handleRoot(HTTPRequest *req, HTTPResponse *res);
|
void handleRoot(HTTPRequest *req, HTTPResponse *res);
|
||||||
void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res);
|
void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res);
|
||||||
|
void handleStaticPost(HTTPRequest *req, HTTPResponse *res);
|
||||||
void handleStatic(HTTPRequest *req, HTTPResponse *res);
|
void handleStatic(HTTPRequest *req, HTTPResponse *res);
|
||||||
void handle404(HTTPRequest *req, HTTPResponse *res);
|
void handle404(HTTPRequest *req, HTTPResponse *res);
|
||||||
void handleFormUpload(HTTPRequest *req, HTTPResponse *res);
|
void handleFormUpload(HTTPRequest *req, HTTPResponse *res);
|
||||||
|
@ -229,6 +230,7 @@ void initWebServer()
|
||||||
ResourceNode *nodeFavicon = new ResourceNode("/favicon.ico", "GET", &handleFavicon);
|
ResourceNode *nodeFavicon = new ResourceNode("/favicon.ico", "GET", &handleFavicon);
|
||||||
ResourceNode *nodeRoot = new ResourceNode("/", "GET", &handleRoot);
|
ResourceNode *nodeRoot = new ResourceNode("/", "GET", &handleRoot);
|
||||||
ResourceNode *nodeStaticBrowse = new ResourceNode("/static", "GET", &handleStaticBrowse);
|
ResourceNode *nodeStaticBrowse = new ResourceNode("/static", "GET", &handleStaticBrowse);
|
||||||
|
ResourceNode *nodeStaticPOST = new ResourceNode("/static", "POST", &handleStaticPost);
|
||||||
ResourceNode *nodeStatic = new ResourceNode("/static/*", "GET", &handleStatic);
|
ResourceNode *nodeStatic = new ResourceNode("/static/*", "GET", &handleStatic);
|
||||||
ResourceNode *node404 = new ResourceNode("", "GET", &handle404);
|
ResourceNode *node404 = new ResourceNode("", "GET", &handle404);
|
||||||
ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
|
ResourceNode *nodeFormUpload = new ResourceNode("/upload", "POST", &handleFormUpload);
|
||||||
|
@ -241,6 +243,7 @@ void initWebServer()
|
||||||
secureServer->registerNode(nodeFavicon);
|
secureServer->registerNode(nodeFavicon);
|
||||||
secureServer->registerNode(nodeRoot);
|
secureServer->registerNode(nodeRoot);
|
||||||
secureServer->registerNode(nodeStaticBrowse);
|
secureServer->registerNode(nodeStaticBrowse);
|
||||||
|
secureServer->registerNode(nodeStaticPOST);
|
||||||
secureServer->registerNode(nodeStatic);
|
secureServer->registerNode(nodeStatic);
|
||||||
secureServer->setDefaultNode(node404);
|
secureServer->setDefaultNode(node404);
|
||||||
secureServer->setDefaultNode(nodeFormUpload);
|
secureServer->setDefaultNode(nodeFormUpload);
|
||||||
|
@ -255,6 +258,7 @@ void initWebServer()
|
||||||
insecureServer->registerNode(nodeFavicon);
|
insecureServer->registerNode(nodeFavicon);
|
||||||
insecureServer->registerNode(nodeRoot);
|
insecureServer->registerNode(nodeRoot);
|
||||||
insecureServer->registerNode(nodeStaticBrowse);
|
insecureServer->registerNode(nodeStaticBrowse);
|
||||||
|
insecureServer->registerNode(nodeStaticPOST);
|
||||||
insecureServer->registerNode(nodeStatic);
|
insecureServer->registerNode(nodeStatic);
|
||||||
insecureServer->setDefaultNode(node404);
|
insecureServer->setDefaultNode(node404);
|
||||||
insecureServer->setDefaultNode(nodeFormUpload);
|
insecureServer->setDefaultNode(nodeFormUpload);
|
||||||
|
@ -294,11 +298,82 @@ void middlewareSpeedUp160(HTTPRequest *req, HTTPResponse *res, std::function<voi
|
||||||
}
|
}
|
||||||
timeSpeedUp = millis();
|
timeSpeedUp = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleStaticPost(HTTPRequest *req, HTTPResponse *res)
|
||||||
|
{
|
||||||
|
// Assume POST request. Contains submitted data.
|
||||||
|
res->println("<html><head><title>File Edited</title><meta http-equiv=\"refresh\" content=\"3;url=/static\" "
|
||||||
|
"/><head><body><h1>File Edited</h1>");
|
||||||
|
|
||||||
|
// The form is submitted with the x-www-form-urlencoded content type, so we need the
|
||||||
|
// HTTPURLEncodedBodyParser to read the fields.
|
||||||
|
// Note that the content of the file's content comes from a <textarea>, so we
|
||||||
|
// can use the URL encoding here, since no file upload from an <input type="file"
|
||||||
|
// is involved.
|
||||||
|
HTTPURLEncodedBodyParser parser(req);
|
||||||
|
|
||||||
|
// The bodyparser will consume the request body. That means you can iterate over the
|
||||||
|
// fields only ones. For that reason, we need to create variables for all fields that
|
||||||
|
// we expect. So when parsing is done, you can process the field values from your
|
||||||
|
// temporary variables.
|
||||||
|
std::string filename;
|
||||||
|
bool savedFile = false;
|
||||||
|
|
||||||
|
// Iterate over the fields from the request body by calling nextField(). This function
|
||||||
|
// will update the field name and value of the body parsers. If the last field has been
|
||||||
|
// reached, it will return false and the while loop stops.
|
||||||
|
while (parser.nextField()) {
|
||||||
|
// Get the field name, so that we can decide what the value is for
|
||||||
|
std::string name = parser.getFieldName();
|
||||||
|
|
||||||
|
if (name == "filename") {
|
||||||
|
// Read the filename from the field's value, add the /public prefix and store it in
|
||||||
|
// the filename variable.
|
||||||
|
char buf[512];
|
||||||
|
size_t readLength = parser.read((byte *)buf, 512);
|
||||||
|
// filename = std::string("/public/") + std::string(buf, readLength);
|
||||||
|
filename = std::string(buf, readLength);
|
||||||
|
|
||||||
|
} else if (name == "content") {
|
||||||
|
// Browsers must return the fields in the order that they are placed in
|
||||||
|
// the HTML form, so if the broweser behaves correctly, this condition will
|
||||||
|
// never be true. We include it for safety reasons.
|
||||||
|
if (filename == "") {
|
||||||
|
res->println("<p>Error: form contained content before filename.</p>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// With parser.read() and parser.endOfField(), we can stream the field content
|
||||||
|
// into a buffer. That allows handling arbitrarily-sized field contents. Here,
|
||||||
|
// we use it and write the file contents directly to the SPIFFS:
|
||||||
|
size_t fieldLength = 0;
|
||||||
|
File file = SPIFFS.open(filename.c_str(), "w");
|
||||||
|
savedFile = true;
|
||||||
|
while (!parser.endOfField()) {
|
||||||
|
byte buf[512];
|
||||||
|
size_t readLength = parser.read(buf, 512);
|
||||||
|
file.write(buf, readLength);
|
||||||
|
fieldLength += readLength;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
res->printf("<p>Saved %d bytes to %s</p>", int(fieldLength), filename.c_str());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
res->printf("<p>Unexpected field %s</p>", name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!savedFile) {
|
||||||
|
res->println("<p>No file to save...</p>");
|
||||||
|
}
|
||||||
|
res->println("</body></html>");
|
||||||
|
}
|
||||||
|
|
||||||
void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res)
|
void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res)
|
||||||
{
|
{
|
||||||
// Get access to the parameters
|
// Get access to the parameters
|
||||||
ResourceParameters *params = req->getParams();
|
ResourceParameters *params = req->getParams();
|
||||||
std::string paramValDelete;
|
std::string paramValDelete;
|
||||||
|
std::string paramValEdit;
|
||||||
|
|
||||||
// Set a default content type
|
// Set a default content type
|
||||||
res->setHeader("Content-Type", "text/html");
|
res->setHeader("Content-Type", "text/html");
|
||||||
|
@ -323,6 +398,47 @@ void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params->getQueryParameter("edit", paramValEdit)) {
|
||||||
|
std::string pathEdit = "/" + paramValEdit;
|
||||||
|
res->println("<html><head><title>Edit "
|
||||||
|
"file</title></head><body><h1>Edit file - ");
|
||||||
|
|
||||||
|
res->println(pathEdit.c_str());
|
||||||
|
|
||||||
|
res->println("</h1>");
|
||||||
|
res->println("<form method=post action=/static enctype=application/x-www-form-urlencoded>");
|
||||||
|
res->printf("<input name=\"filename\" type=\"hidden\" value=\"%s\">", pathEdit.c_str());
|
||||||
|
res->print("<textarea id=id name=content rows=20 cols=80>");
|
||||||
|
|
||||||
|
// Try to open the file from SPIFFS
|
||||||
|
File file = SPIFFS.open(pathEdit.c_str());
|
||||||
|
|
||||||
|
if (file.available()) {
|
||||||
|
// Read the file from SPIFFS and write it to the HTTP response body
|
||||||
|
size_t length = 0;
|
||||||
|
do {
|
||||||
|
char buffer[256];
|
||||||
|
length = file.read((uint8_t *)buffer, 256);
|
||||||
|
std::string bufferString(buffer, length);
|
||||||
|
|
||||||
|
// Escape gt and lt
|
||||||
|
replaceAll(bufferString, "<", "<");
|
||||||
|
replaceAll(bufferString, ">", ">");
|
||||||
|
|
||||||
|
res->write((uint8_t *)bufferString.c_str(), bufferString.size());
|
||||||
|
} while (length > 0);
|
||||||
|
} else {
|
||||||
|
res->println("Error: File not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
res->println("</textarea><br>");
|
||||||
|
res->println("<input type=submit value=Submit>");
|
||||||
|
res->println("</form>");
|
||||||
|
res->println("</body></html>");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
res->println("<h2>Upload new file</h2>");
|
res->println("<h2>Upload new file</h2>");
|
||||||
res->println("<p><b>*** This interface is experimental ***</b></p>");
|
res->println("<p><b>*** This interface is experimental ***</b></p>");
|
||||||
res->println("<p>This form allows you to upload files. Keep your filenames very short and files small. Big filenames and big "
|
res->println("<p>This form allows you to upload files. Keep your filenames very short and files small. Big filenames and big "
|
||||||
|
@ -339,6 +455,15 @@ void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res)
|
||||||
res->println("<script type=\"text/javascript\">function confirm_delete() {return confirm('Are you sure?');}</script>");
|
res->println("<script type=\"text/javascript\">function confirm_delete() {return confirm('Are you sure?');}</script>");
|
||||||
|
|
||||||
res->println("<table>");
|
res->println("<table>");
|
||||||
|
res->println("<tr>");
|
||||||
|
res->println("<td>File");
|
||||||
|
res->println("</td>");
|
||||||
|
res->println("<td>Size");
|
||||||
|
res->println("</td>");
|
||||||
|
res->println("<td colspan=2>Actions");
|
||||||
|
res->println("</td>");
|
||||||
|
res->println("</tr>");
|
||||||
|
|
||||||
File file = root.openNextFile();
|
File file = root.openNextFile();
|
||||||
while (file) {
|
while (file) {
|
||||||
String filePath = String(file.name());
|
String filePath = String(file.name());
|
||||||
|
@ -360,8 +485,14 @@ void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res)
|
||||||
res->println("</td>");
|
res->println("</td>");
|
||||||
res->println("<td>");
|
res->println("<td>");
|
||||||
res->print("<a href=\"/static?delete=" + String(file.name()).substring(1) +
|
res->print("<a href=\"/static?delete=" + String(file.name()).substring(1) +
|
||||||
"\" onclick=\"return confirm_delete()\">X</a>");
|
"\" onclick=\"return confirm_delete()\">Delete</a> ");
|
||||||
res->println("</td>");
|
res->println("</td>");
|
||||||
|
res->println("<td>");
|
||||||
|
if (!String(file.name()).substring(1).endsWith(".gz")) {
|
||||||
|
res->print("<a href=\"/static?edit=" + String(file.name()).substring(1) + "\">Edit</a>");
|
||||||
|
}
|
||||||
|
res->println("</td>");
|
||||||
|
res->println("</tr>");
|
||||||
}
|
}
|
||||||
|
|
||||||
file = root.openNextFile();
|
file = root.openNextFile();
|
||||||
|
@ -369,7 +500,7 @@ void handleStaticBrowse(HTTPRequest *req, HTTPResponse *res)
|
||||||
res->println("</table>");
|
res->println("</table>");
|
||||||
|
|
||||||
res->print("<br>");
|
res->print("<br>");
|
||||||
res->print("Total : " + String(SPIFFS.totalBytes()) + " Bytes<br>");
|
// res->print("Total : " + String(SPIFFS.totalBytes()) + " Bytes<br>");
|
||||||
res->print("Used : " + String(SPIFFS.usedBytes()) + " Bytes<br>");
|
res->print("Used : " + String(SPIFFS.usedBytes()) + " Bytes<br>");
|
||||||
res->print("Free : " + String(SPIFFS.totalBytes() - SPIFFS.usedBytes()) + " Bytes<br>");
|
res->print("Free : " + String(SPIFFS.totalBytes() - SPIFFS.usedBytes()) + " Bytes<br>");
|
||||||
}
|
}
|
||||||
|
@ -700,8 +831,19 @@ void handleAPIv1ToRadio(HTTPRequest *req, HTTPResponse *res)
|
||||||
*/
|
*/
|
||||||
void handleRoot(HTTPRequest *req, HTTPResponse *res)
|
void handleRoot(HTTPRequest *req, HTTPResponse *res)
|
||||||
{
|
{
|
||||||
|
|
||||||
res->setHeader("Content-Type", "text/html");
|
res->setHeader("Content-Type", "text/html");
|
||||||
|
|
||||||
|
randomSeed(millis());
|
||||||
|
|
||||||
|
res->setHeader("Set-Cookie",
|
||||||
|
"mt_session=" + httpsserver::intToString(random(1, 9999999)) + "; Expires=Wed, 20 Apr 2049 4:20:00 PST");
|
||||||
|
|
||||||
|
std::string cookie = req->getHeader("Cookie");
|
||||||
|
//String cookieString = cookie.c_str();
|
||||||
|
//uint8_t nameIndex = cookieString.indexOf("mt_session");
|
||||||
|
//DEBUG_MSG(cookie.c_str());
|
||||||
|
|
||||||
std::string filename = "/static/index.html";
|
std::string filename = "/static/index.html";
|
||||||
std::string filenameGzip = "/static/index.html.gz";
|
std::string filenameGzip = "/static/index.html.gz";
|
||||||
|
|
||||||
|
@ -748,3 +890,14 @@ void handleFavicon(HTTPRequest *req, HTTPResponse *res)
|
||||||
// Write data from header file
|
// Write data from header file
|
||||||
res->write(FAVICON_DATA, FAVICON_LENGTH);
|
res->write(FAVICON_DATA, FAVICON_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void replaceAll(std::string &str, const std::string &from, const std::string &to)
|
||||||
|
{
|
||||||
|
if (from.empty())
|
||||||
|
return;
|
||||||
|
size_t start_pos = 0;
|
||||||
|
while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||||
|
str.replace(start_pos, from.length(), to);
|
||||||
|
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,8 @@ void handleRoot();
|
||||||
void handleScriptsScriptJS();
|
void handleScriptsScriptJS();
|
||||||
void handleJSONChatHistoryDummy();
|
void handleJSONChatHistoryDummy();
|
||||||
|
|
||||||
|
void replaceAll(std::string& str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
class HttpAPI : public PhoneAPI
|
class HttpAPI : public PhoneAPI
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue