| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362 |
- /* HTTP File Server Example
- This example code is in the Public Domain (or CC0 licensed, at your option.)
- Unless required by applicable law or agreed to in writing, this
- software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- CONDITIONS OF ANY KIND, either express or implied.
- */
- #include "defines.h"
- #include "server_file.h"
- #include <stdio.h>
- #include <string.h>
- #include <string>
- #include <sys/param.h>
- #include <sys/unistd.h>
- #include <sys/stat.h>
- #include <iostream>
- #include <sys/types.h>
- #include <dirent.h>
- #include "esp_err.h"
- #include "esp_log.h"
- #include "esp_vfs.h"
- #include <esp_spiffs.h>
- #include "esp_http_server.h"
- #include "ClassLogFile.h"
- #include "MainFlowControl.h"
- #include "server_help.h"
- #include "md5.h"
- #include "interface_mqtt.h"
- #include "server_GPIO.h"
- #include "Helper.h"
- #include "miniz.h"
- #include "basic_auth.h"
- static const char *TAG = "OTA FILE";
- using namespace std;
- string TEMP_SUFFIX = "_tmp";
- static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file);
- static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file);
- struct file_server_data
- {
- /* Base path of file storage */
- char base_path[ESP_VFS_PATH_MAX + 1];
- /* Scratch buffer for temporary storage during file transfer */
- char scratch[SERVER_FILER_SCRATCH_BUFSIZE];
- };
- esp_err_t get_numbers_file_handler(httpd_req_t *req)
- {
- std::string ret = flowctrl.getNumbersName();
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- httpd_resp_set_type(req, "text/plain");
- httpd_resp_sendstr_chunk(req, ret.c_str());
- httpd_resp_sendstr_chunk(req, NULL);
- return ESP_OK;
- }
- esp_err_t get_data_file_handler(httpd_req_t *req)
- {
- struct dirent *entry;
- std::string _filename, _fileext;
- size_t pos = 0;
- const char verz_name[] = "/sdcard/log/data";
- ESP_LOGD(TAG, "Suche data files in /sdcard/log/data");
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- httpd_resp_set_type(req, "text/plain");
- DIR *pDir = opendir(verz_name);
- while ((entry = readdir(pDir)) != NULL)
- {
- _filename = std::string(entry->d_name);
- ESP_LOGD(TAG, "File: %s", _filename.c_str());
- // ignore all files with starting dot (hidden files)
- if (_filename.rfind(".", 0) == 0)
- {
- continue;
- }
- _fileext = _filename;
- pos = _fileext.find_last_of(".");
- if (pos != std::string::npos)
- {
- _fileext = _fileext.erase(0, pos + 1);
- }
- ESP_LOGD(TAG, " Extension: %s", _fileext.c_str());
- if (_fileext == "csv")
- {
- _filename = _filename + "\t";
- httpd_resp_sendstr_chunk(req, _filename.c_str());
- }
- }
- closedir(pDir);
- httpd_resp_sendstr_chunk(req, NULL);
- return ESP_OK;
- }
- esp_err_t get_tflite_file_handler(httpd_req_t *req)
- {
- struct dirent *entry;
- std::string _filename, _fileext;
- size_t pos = 0;
- const char verz_name[] = "/sdcard/config";
- ESP_LOGD(TAG, "Suche TFLITE in /sdcard/config/");
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- httpd_resp_set_type(req, "text/plain");
- DIR *pDir = opendir(verz_name);
- while ((entry = readdir(pDir)) != NULL)
- {
- _filename = std::string(entry->d_name);
- ESP_LOGD(TAG, "File: %s", _filename.c_str());
- // ignore all files with starting dot (hidden files)
- if (_filename.rfind(".", 0) == 0)
- {
- continue;
- }
- _fileext = _filename;
- pos = _fileext.find_last_of(".");
- if (pos != std::string::npos)
- {
- _fileext = _fileext.erase(0, pos + 1);
- }
- ESP_LOGD(TAG, " Extension: %s", _fileext.c_str());
- if ((_fileext == "tfl") || (_fileext == "tflite"))
- {
- _filename = "/config/" + _filename + "\t";
- httpd_resp_sendstr_chunk(req, _filename.c_str());
- }
- }
- closedir(pDir);
- httpd_resp_sendstr_chunk(req, NULL);
- return ESP_OK;
- }
- /* Send HTTP response with a run-time generated html consisting of
- * a list of all files and folders under the requested path.
- * In case of SPIFFS this returns empty list when path is any
- * string other than '/', since SPIFFS doesn't support directories */
- static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const char *uripath, bool readonly)
- {
- char entrypath[FILE_PATH_MAX];
- char dirpath_corrected[FILE_PATH_MAX];
- strcpy(dirpath_corrected, dirpath);
- file_server_data *server_data = (file_server_data *)req->user_ctx;
- if ((strlen(dirpath_corrected) - 1) > strlen(server_data->base_path))
- {
- // if dirpath is not mountpoint, the last "\" needs to be removed
- dirpath_corrected[strlen(dirpath_corrected) - 1] = '\0';
- }
- DIR *pdir = opendir(dirpath_corrected);
- const size_t dirpath_len = strlen(dirpath);
- ESP_LOGD(TAG, "Dirpath: <%s>, Pathlength: %d", dirpath, dirpath_len);
- // Retrieve the base path of file storage to construct the full path
- strlcpy(entrypath, dirpath, sizeof(entrypath));
- ESP_LOGD(TAG, "entrypath: <%s>", entrypath);
- if (!pdir)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat dir: " + std::string(dirpath) + "!");
- // Respond with 404 Not Found
- httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
- return ESP_FAIL;
- }
- char entrysize[16];
- const char *entrytype;
- struct dirent *entry;
- struct stat entry_stat;
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- // Send HTML file header
- httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html lang=\"en\" xml:lang=\"en\"><head>");
- httpd_resp_sendstr_chunk(req, "<link type=\"image/png\" href=\"/close.png\" rel=\"icon\">");
- httpd_resp_sendstr_chunk(req, "<link href=\"/file_server.css\" rel=\"stylesheet\">");
- httpd_resp_sendstr_chunk(req, "<link href=\"/firework.css\" rel=\"stylesheet\">");
- httpd_resp_sendstr_chunk(req, "<script type=\"text/javascript\" src=\"/jquery-3.6.0.min.js\"></script>");
- httpd_resp_sendstr_chunk(req, "<script type=\"text/javascript\" src=\"/firework.js\"></script></head>");
- httpd_resp_sendstr_chunk(req, "<body>");
- httpd_resp_sendstr_chunk(req, "<table class=\"fixed\" border=\"0\" width=100% style=\"font-family: arial\">");
- httpd_resp_sendstr_chunk(req, "<tr><td style=\"vertical-align: top;width: 300px;\"><h2>Fileserver</h2></td>"
- "<td rowspan=\"2\"><table border=\"0\" style=\"width:100%\"><tr><td style=\"width:80px\">"
- "<label for=\"newfile\">Source</label></td><td colspan=\"2\">"
- "<input id=\"newfile\" type=\"file\" onchange=\"setpath()\" style=\"width:100%;\"></td></tr>"
- "<tr><td><label for=\"filepath\">Destination</label></td><td>"
- "<input id=\"filepath\" type=\"text\" style=\"width:94%;\"></td><td>"
- "<button id=\"upload\" type=\"button\" class=\"button\" onclick=\"upload()\">Upload</button></td></tr>"
- "</table></td></tr><tr></tr><tr><td colspan=\"2\">"
- "<button style=\"font-size:16px; padding: 5px 10px\" id=\"dirup\" type=\"button\" onclick=\"dirup()\""
- "disabled>🡹 Directory up</button><span style=\"padding-left:15px\" id=\"currentpath\">"
- "</span></td></tr>");
- httpd_resp_sendstr_chunk(req, "</table>");
- httpd_resp_sendstr_chunk(req, "<script type=\"text/javascript\" src=\"/file_server.js\"></script>");
- httpd_resp_sendstr_chunk(req, "<script type=\"text/javascript\">initFileServer();</script>");
- std::string temp_string = std::string(dirpath);
- temp_string = temp_string.substr(8, temp_string.length() - 8);
- temp_string = "/delete/" + temp_string + "?task=deldircontent";
- // Send file-list table definition and column labels
- httpd_resp_sendstr_chunk(req, "<table id=\"files_table\">"
- "<col width=\"800px\"><col width=\"300px\"><col width=\"300px\"><col width=\"100px\">"
- "<thead><tr><th>Name</th><th>Type</th><th>Size</th>");
- if (!readonly)
- {
- httpd_resp_sendstr_chunk(req, "<th><form method=\"post\" action=\"");
- httpd_resp_sendstr_chunk(req, temp_string.c_str());
- httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">DELETE ALL!</button></form></th></tr>");
- }
- httpd_resp_sendstr_chunk(req, "</thead><tbody>\n");
- // Iterate over all files / folders and fetch their names and sizes
- while ((entry = readdir(pdir)) != NULL)
- {
- // wlan.ini soll nicht angezeigt werden!
- if ((strcmp("wlan.ini", entry->d_name) != 0) || (strcmp("network.ini", entry->d_name) != 0))
- {
- entrytype = (entry->d_type == DT_DIR ? "directory" : "file");
- strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
- ESP_LOGD(TAG, "Entrypath: %s", entrypath);
- if (stat(entrypath, &entry_stat) == -1)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat " + std::string(entrytype) + ": " + std::string(entry->d_name));
- continue;
- }
- if (entry->d_type == DT_DIR)
- {
- strcpy(entrysize, "-\0");
- }
- else
- {
- if (entry_stat.st_size >= 1024)
- {
- sprintf(entrysize, "%ld KiB", entry_stat.st_size / 1024); // kBytes
- }
- else
- {
- sprintf(entrysize, "%ld B", entry_stat.st_size); // Bytes
- }
- }
- ESP_LOGD(TAG, "Found %s: %s (%s bytes)", entrytype, entry->d_name, entrysize);
- // Send chunk of HTML file containing table entries with file name and size
- httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
- httpd_resp_sendstr_chunk(req, "/fileserver");
- httpd_resp_sendstr_chunk(req, uripath);
- httpd_resp_sendstr_chunk(req, entry->d_name);
- if (entry->d_type == DT_DIR)
- {
- httpd_resp_sendstr_chunk(req, "/");
- }
- httpd_resp_sendstr_chunk(req, "\">");
- httpd_resp_sendstr_chunk(req, entry->d_name);
- httpd_resp_sendstr_chunk(req, "</a></td><td>");
- httpd_resp_sendstr_chunk(req, entrytype);
- httpd_resp_sendstr_chunk(req, "</td><td>");
- httpd_resp_sendstr_chunk(req, entrysize);
- if (!readonly)
- {
- httpd_resp_sendstr_chunk(req, "</td><td>");
- httpd_resp_sendstr_chunk(req, "<form method=\"post\" action=\"/delete");
- httpd_resp_sendstr_chunk(req, uripath);
- httpd_resp_sendstr_chunk(req, entry->d_name);
- httpd_resp_sendstr_chunk(req, "\"><button type=\"submit\">Delete</button></form>");
- }
- httpd_resp_sendstr_chunk(req, "</td></tr>\n");
- }
- }
- closedir(pdir);
- // Finish the file list table
- httpd_resp_sendstr_chunk(req, "</tbody></table>");
- // Send remaining chunk of HTML file to complete it
- httpd_resp_sendstr_chunk(req, "</body></html>");
- // Send empty chunk to signal HTTP response completion
- httpd_resp_sendstr_chunk(req, NULL);
- return ESP_OK;
- }
- static esp_err_t logfileact_get_full_handler(httpd_req_t *req)
- {
- return send_logfile(req, true);
- }
- static esp_err_t logfileact_get_last_part_handler(httpd_req_t *req)
- {
- return send_logfile(req, false);
- }
- static esp_err_t datafileact_get_full_handler(httpd_req_t *req)
- {
- return send_datafile(req, true);
- }
- static esp_err_t datafileact_get_last_part_handler(httpd_req_t *req)
- {
- return send_datafile(req, false);
- }
- static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
- {
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "data_get_last_part_handler");
- ESP_LOGD(TAG, "uri: %s", req->uri);
- std::string currentfilename = LogFile.GetCurrentFileNameData();
- ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, currentfilename.c_str(), currentfilename.c_str());
- FILE *pFile = fopen(currentfilename.c_str(), "r");
- if (!pFile)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + currentfilename + "!");
- /* Respond with 404 Error */
- httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
- return ESP_FAIL;
- }
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- set_content_type_from_file(req, currentfilename.c_str());
- if (!send_full_file)
- {
- // Send only last part of file
- ESP_LOGD(TAG, "Sending last %d bytes of the actual datafile!", LOGFILE_LAST_PART_BYTES);
- /* Adapted from https://www.geeksforgeeks.org/implement-your-own-tail-read-last-n-lines-of-a-huge-file/ */
- if (fseek(pFile, 0, SEEK_END))
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to get to end of file!");
- return ESP_FAIL;
- }
- else
- {
- long pos = ftell(pFile); // Number of bytes in the file
- ESP_LOGI(TAG, "File contains %ld bytes", pos);
- if (fseek(pFile, pos - std::min((long)LOGFILE_LAST_PART_BYTES, pos), SEEK_SET))
- {
- // Go LOGFILE_LAST_PART_BYTES bytes back from EOF
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to go back " + to_string(std::min((long)LOGFILE_LAST_PART_BYTES, pos)) + " bytes within the file!");
-
- return ESP_FAIL;
- }
- }
- /* Find end of line */
- while (1)
- {
- if (fgetc(pFile) == '\n')
- {
- break;
- }
- }
- }
- /* Retrieve the pointer to scratch buffer for temporary storage */
- char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
- size_t chunksize;
- do
- {
- /* Read file in chunks into the scratch buffer */
- chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, pFile);
- /* Send the buffer contents as HTTP response chunk */
- if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK)
- {
- fclose(pFile);
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File sending failed!");
- /* Abort sending file */
- httpd_resp_sendstr_chunk(req, NULL);
- /* Respond with 500 Internal Server Error */
- httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
- return ESP_FAIL;
- }
- /* Keep looping till the whole file is sent */
- } while (chunksize != 0);
- /* Close file after sending complete */
- fclose(pFile);
- ESP_LOGI(TAG, "File sending complete");
- /* Respond with an empty chunk to signal HTTP response completion */
- httpd_resp_send_chunk(req, NULL, 0);
- return ESP_OK;
- }
- static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
- {
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "log_get_last_part_handler");
- ESP_LOGI(TAG, "uri: %s", req->uri);
- const char *filename = "";
- std::string currentfilename = LogFile.GetCurrentFileName();
- ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, currentfilename.c_str());
- // Since the log file is still could open for writing, we need to close it first
- LogFile.CloseLogFileAppendHandle();
- FILE *pFile = fopen(currentfilename.c_str(), "r");
- if (!pFile)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + currentfilename + "!");
- /* Respond with 404 Error */
- httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
- return ESP_FAIL;
- }
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- set_content_type_from_file(req, filename);
- if (!send_full_file)
- {
- // Send only last part of file
- ESP_LOGD(TAG, "Sending last %d bytes of the actual logfile!", LOGFILE_LAST_PART_BYTES);
- /* Adapted from https://www.geeksforgeeks.org/implement-your-own-tail-read-last-n-lines-of-a-huge-file/ */
- if (fseek(pFile, 0, SEEK_END))
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to get to end of file!");
- return ESP_FAIL;
- }
- else
- {
- long pos = ftell(pFile); // Number of bytes in the file
- ESP_LOGI(TAG, "File contains %ld bytes", pos);
- if (fseek(pFile, pos - std::min((long)LOGFILE_LAST_PART_BYTES, pos), SEEK_SET))
- {
- // Go LOGFILE_LAST_PART_BYTES bytes back from EOF
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to go back " + to_string(std::min((long)LOGFILE_LAST_PART_BYTES, pos)) + " bytes within the file!");
-
- return ESP_FAIL;
- }
- }
- /* Find end of line */
- while (1)
- {
- if (fgetc(pFile) == '\n')
- {
- break;
- }
- }
- }
- /* Retrieve the pointer to scratch buffer for temporary storage */
- char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
- size_t chunksize;
- do
- {
- /* Read file in chunks into the scratch buffer */
- chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, pFile);
- /* Send the buffer contents as HTTP response chunk */
- if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK)
- {
- fclose(pFile);
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File sending failed!");
- /* Abort sending file */
- httpd_resp_sendstr_chunk(req, NULL);
- /* Respond with 500 Internal Server Error */
- httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
- return ESP_FAIL;
- }
- /* Keep looping till the whole file is sent */
- } while (chunksize != 0);
- /* Close file after sending complete */
- fclose(pFile);
- ESP_LOGD(TAG, "File sending complete");
- /* Respond with an empty chunk to signal HTTP response completion */
- httpd_resp_send_chunk(req, NULL, 0);
- return ESP_OK;
- }
- /* Handler to download a file kept on the server */
- static esp_err_t download_get_handler(httpd_req_t *req)
- {
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "download_get_handler");
- char filepath[FILE_PATH_MAX];
- struct stat file_stat;
- ESP_LOGD(TAG, "uri: %s", req->uri);
- const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path, req->uri + sizeof("/fileserver") - 1, sizeof(filepath));
- ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
- if (!filename)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Filename is too long");
- /* Respond with 414 Error */
- httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
- return ESP_FAIL;
- }
- /* If name has trailing '/', respond with directory contents */
- if (filename[strlen(filename) - 1] == '/')
- {
- bool readonly = false;
- size_t buf_len = httpd_req_get_url_query_len(req) + 1;
- if (buf_len > 1)
- {
- char buf[buf_len];
- if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
- {
- ESP_LOGI(TAG, "Found URL query => %s", buf);
- char param[32];
- /* Get value of expected key from query string */
- if (httpd_query_key_value(buf, "readonly", param, sizeof(param)) == ESP_OK)
- {
- ESP_LOGI(TAG, "Found URL query parameter => readonly=%s", param);
- readonly = (strcmp(param, "true") == 0);
- }
- }
- }
- ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
- return http_resp_dir_html(req, filepath, filename, readonly);
- }
- std::string testwlan = to_upper(std::string(filename));
- if ((stat(filepath, &file_stat) == -1) || (testwlan.compare("/WLAN.INI") == 0) || (testwlan.compare("/NETWORK.INI") == 0))
- {
- // wlan.ini soll nicht angezeigt werden!
- /* If file not present on SPIFFS check if URI
- * corresponds to one of the hardcoded paths */
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat file: " + std::string(filepath) + "!");
- /* Respond with 404 Not Found */
- httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
- return ESP_FAIL;
- }
- FILE *pFile = fopen(filepath, "r");
- if (!pFile)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(filepath) + "!");
- /* Respond with 404 Error */
- httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
- return ESP_FAIL;
- }
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- ESP_LOGD(TAG, "Sending file: %s (%ld bytes)...", filename, file_stat.st_size);
- set_content_type_from_file(req, filename);
- /* Retrieve the pointer to scratch buffer for temporary storage */
- char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
- size_t chunksize;
- do
- {
- /* Read file in chunks into the scratch buffer */
- chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, pFile);
- /* Send buffer contents as HTTP chunk. If empty this functions as a
- * last-chunk message, signaling end-of-response, to the HTTP client.
- * See RFC 2616, section 3.6.1 for details on Chunked Transfer Encoding. */
- if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK)
- {
- fclose(pFile);
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File sending failed!");
- /* Abort sending file */
- httpd_resp_sendstr_chunk(req, NULL);
- /* Respond with 500 Internal Server Error */
- httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file!");
- return ESP_FAIL;
- }
- /* Keep looping till the whole file is sent */
- } while (chunksize != 0);
- /* Close file after sending complete */
- fclose(pFile);
- ESP_LOGD(TAG, "File successfully sent");
- return ESP_OK;
- }
- /* Handler to upload a file onto the server */
- static esp_err_t upload_post_handler(httpd_req_t *req)
- {
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "upload_post_handler");
- char filepath[FILE_PATH_MAX];
- ESP_LOGI(TAG, "uri: %s", req->uri);
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- /* Skip leading "/upload" from URI to get filename */
- /* Note sizeof() counts NULL termination hence the -1 */
- const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path, req->uri + sizeof("/upload") - 1, sizeof(filepath));
- if (!filename)
- {
- /* Respond with 413 Error */
- httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
- return ESP_FAIL;
- }
- /* Filename cannot have a trailing '/' */
- if (filename[strlen(filename) - 1] == '/')
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Invalid filename: " + string(filename));
- /* Respond with 400 Bad Request */
- httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid filename");
- return ESP_FAIL;
- }
- struct stat file_stat;
- if (stat(filepath, &file_stat) == 0)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File already exists: " + string(filepath));
- /* Respond with 400 Bad Request */
- httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File already exists");
- return ESP_FAIL;
- }
- /* File cannot be larger than a limit */
- if (req->content_len > MAX_FILE_SIZE)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File too large: " + to_string(req->content_len) + " bytes");
- /* Respond with 400 Bad Request */
- httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File size must be less than " MAX_FILE_SIZE_STR "!");
- /* Return failure to close underlying connection else the
- * incoming file content will keep the socket busy */
- return ESP_FAIL;
- }
- FILE *pFile = fopen(filepath, "w");
- if (!pFile)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create file: " + string(filepath));
- /* Respond with 500 Internal Server Error */
- httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create file");
- return ESP_FAIL;
- }
- ESP_LOGI(TAG, "Receiving file: %s...", filename);
- /* Retrieve the pointer to scratch buffer for temporary storage */
- char *buf = ((struct file_server_data *)req->user_ctx)->scratch;
- int received;
- /* Content length of the request gives
- * the size of the file being uploaded */
- int remaining = req->content_len;
- while (remaining > 0)
- {
- ESP_LOGI(TAG, "Remaining size: %d", remaining);
- /* Receive the file part by part into a buffer */
- if ((received = httpd_req_recv(req, buf, MIN(remaining, SERVER_FILER_SCRATCH_BUFSIZE))) <= 0)
- {
- if (received == HTTPD_SOCK_ERR_TIMEOUT)
- {
- /* Retry if timeout occurred */
- continue;
- }
- /* In case of unrecoverable error,
- * close and delete the unfinished file*/
- fclose(pFile);
- unlink(filepath);
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File reception failed!");
- /* Respond with 500 Internal Server Error */
- httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
- return ESP_FAIL;
- }
- /* Write buffer content to file on storage */
- if (received && (received != fwrite(buf, 1, received, pFile)))
- {
- /* Couldn't write everything to file!
- * Storage may be full? */
- fclose(pFile);
- unlink(filepath);
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File write failed!");
- /* Respond with 500 Internal Server Error */
- httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to write file to storage");
- return ESP_FAIL;
- }
- /* Keep track of remaining size of
- * the file left to be uploaded */
- remaining -= received;
- }
- /* Close file upon upload completion */
- fclose(pFile);
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "File saved: " + string(filename));
- ESP_LOGI(TAG, "File reception completed");
- string s = req->uri;
- if (is_in_string(s, "?md5"))
- {
- LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Calculate and return MD5 sum...");
- pFile = fopen(filepath, "r");
- if (!pFile)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to open file for reading: " + string(filepath));
- /* Respond with 500 Internal Server Error */
- httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to open file for reading");
- return ESP_FAIL;
- }
- uint8_t result[16];
- string md5hex = "";
- string response = "{\"md5\":";
- char hex[3];
- md5File(pFile, result);
- fclose(pFile);
- for (int i = 0; i < sizeof(result); i++)
- {
- snprintf(hex, sizeof(hex), "%02x", result[i]);
- md5hex.append(hex);
- }
- LogFile.WriteToFile(ESP_LOG_INFO, TAG, "MD5 of " + string(filepath) + ": " + md5hex);
- response.append("\"" + md5hex + "\"");
- response.append("}");
- httpd_resp_sendstr(req, response.c_str());
- }
- else
- {
- // Return file server page
- std::string directory = std::string(filepath);
- size_t temp_size = directory.find("/");
- size_t found = temp_size;
- while (temp_size != std::string::npos)
- {
- temp_size = directory.find("/", found + 1);
- if (temp_size != std::string::npos)
- {
- found = temp_size;
- }
- }
- int start_filename = strlen(((struct file_server_data *)req->user_ctx)->base_path);
- ESP_LOGD(TAG, "Directory: %s, start_filename: %d, found: %d", directory.c_str(), start_filename, found);
- directory = directory.substr(start_filename, found - start_filename + 1);
- directory = "/fileserver" + directory;
- /* Redirect onto root to see the updated file list */
- if (strcmp(filename, "/config/config.ini") == 0 ||
- strcmp(filename, "/config/ref0.jpg") == 0 ||
- strcmp(filename, "/config/ref0_org.jpg") == 0 ||
- strcmp(filename, "/config/ref1.jpg") == 0 ||
- strcmp(filename, "/config/ref1_org.jpg") == 0 ||
- strcmp(filename, "/config/reference.jpg") == 0 ||
- strcmp(filename, "/img_tmp/ref0.jpg") == 0 ||
- strcmp(filename, "/img_tmp/ref0_org.jpg") == 0 ||
- strcmp(filename, "/img_tmp/ref1.jpg") == 0 ||
- strcmp(filename, "/img_tmp/ref1_org.jpg") == 0 ||
- strcmp(filename, "/img_tmp/reference.jpg") == 0)
- {
- httpd_resp_set_status(req, HTTPD_200); // Avoid reloading of folder content
- }
- else
- {
- httpd_resp_set_status(req, "303 See Other"); // Reload folder content after upload
- }
- httpd_resp_set_hdr(req, "Location", directory.c_str());
- httpd_resp_sendstr(req, "File uploaded successfully");
- }
- return ESP_OK;
- }
- /* Handler to delete a file from the server */
- static esp_err_t delete_post_handler(httpd_req_t *req)
- {
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "delete_post_handler");
- char filepath[FILE_PATH_MAX];
- struct stat file_stat;
- //////////////////////////////////////////////////////////////
- char _query[200];
- char _valuechar[30];
- std::string _task;
- std::string directory;
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK)
- {
- ESP_LOGD(TAG, "Query: %s", _query);
- if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK)
- {
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "task is found: " + string(_valuechar));
- _task = std::string(_valuechar);
- }
- }
- if (_task.compare("deldircontent") == 0)
- {
- /* Skip leading "/delete" from URI to get filename */
- /* Note sizeof() counts NULL termination hence the -1 */
- const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path, req->uri + sizeof("/delete") - 1, sizeof(filepath));
- if (!filename)
- {
- /* Respond with 414 Error */
- httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
- return ESP_FAIL;
- }
- std::string temp_filename = std::string(filename);
- temp_filename = temp_filename.substr(0, temp_filename.length() - 1);
- directory = "/fileserver" + temp_filename + "/";
- temp_filename = "/sdcard" + temp_filename;
- ESP_LOGD(TAG, "Directory to delete: %s", temp_filename.c_str());
- delete_all_in_directory(temp_filename);
- ESP_LOGD(TAG, "Location after delete directory content: %s", directory.c_str());
- }
- else
- {
- /* Skip leading "/delete" from URI to get filename */
- /* Note sizeof() counts NULL termination hence the -1 */
- const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path, req->uri + sizeof("/delete") - 1, sizeof(filepath));
- if (!filename)
- {
- /* Respond with 500 Internal Server Error */
- httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
- return ESP_FAIL;
- }
- /* Filename cannot have a trailing '/' */
- if (filename[strlen(filename) - 1] == '/')
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Invalid filename: " + string(filename));
- /* Respond with 400 Bad Request */
- httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid filename");
- return ESP_FAIL;
- }
- if ((strcmp(filename, "wlan.ini") == 0) || (strcmp(filename, "network.ini") == 0))
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to delete protected file : " + string(filename));
- httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Not allowed to delete wlan.ini");
- return ESP_FAIL;
- }
- if (stat(filepath, &file_stat) == -1)
- {
- // File does not exist
- /* This is ok, we would delete it anyway */
- LogFile.WriteToFile(ESP_LOG_INFO, TAG, "File does not exist: " + string(filename));
- }
- /* Delete file */
- unlink(filepath);
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "File deleted: " + string(filename));
- ESP_LOGI(TAG, "File deletion completed");
- directory = std::string(filepath);
- size_t temp_size = directory.find("/");
- size_t found = temp_size;
- while (temp_size != std::string::npos)
- {
- temp_size = directory.find("/", found + 1);
- if (temp_size != std::string::npos)
- {
- found = temp_size;
- }
- }
- int start_filename = strlen(((struct file_server_data *)req->user_ctx)->base_path);
- ESP_LOGD(TAG, "Directory: %s, start_fn: %d, found: %d", directory.c_str(), start_filename, found);
- directory = directory.substr(start_filename, found - start_filename + 1);
- directory = "/fileserver" + directory;
- ESP_LOGD(TAG, "Directory danach 4: %s", directory.c_str());
- //////////////////////////////////////////////////////////////
- /* Redirect onto root to see the updated file list */
- if (strcmp(filename, "/config/config.ini") == 0 ||
- strcmp(filename, "/config/ref0.jpg") == 0 ||
- strcmp(filename, "/config/ref0_org.jpg") == 0 ||
- strcmp(filename, "/config/ref1.jpg") == 0 ||
- strcmp(filename, "/config/ref1_org.jpg") == 0 ||
- strcmp(filename, "/config/reference.jpg") == 0 ||
- strcmp(filename, "/img_tmp/ref0.jpg") == 0 ||
- strcmp(filename, "/img_tmp/ref0_org.jpg") == 0 ||
- strcmp(filename, "/img_tmp/ref1.jpg") == 0 ||
- strcmp(filename, "/img_tmp/ref1_org.jpg") == 0 ||
- strcmp(filename, "/img_tmp/reference.jpg") == 0)
- {
- httpd_resp_set_status(req, HTTPD_200); // Avoid reloading of folder content
- }
- else
- {
- httpd_resp_set_status(req, "303 See Other"); // Reload folder content after upload
- }
- }
- httpd_resp_set_hdr(req, "Location", directory.c_str());
- httpd_resp_sendstr(req, "File successfully deleted");
- return ESP_OK;
- }
- void delete_all_in_directory(std::string _directory)
- {
- DIR *pDir = opendir(_directory.c_str());
- if (!pDir)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat dir: " + _directory);
- return;
- }
- struct dirent *entry;
- std::string filename;
- /* Iterate over all files / folders and fetch their names and sizes */
- while ((entry = readdir(pDir)) != NULL)
- {
- if (!(entry->d_type == DT_DIR))
- {
- if ((strcmp("wlan.ini", entry->d_name) != 0) || (strcmp("network.ini", entry->d_name) != 0))
- {
- // auf wlan.ini soll nicht zugegriffen werden !!!
- filename = _directory + "/" + std::string(entry->d_name);
- LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Deleting file: " + filename);
- /* Delete file */
- unlink(filename.c_str());
- }
- };
- }
- closedir(pDir);
- }
- std::string unzip_new(std::string _in_zip_file, std::string _html_tmp, std::string _html_final, std::string _target_bin, std::string _main, bool _initial_setup)
- {
- ESP_LOGD(TAG, "minizip.c version: %s", MZ_VERSION);
- ESP_LOGD(TAG, "Zipfile: %s", _in_zip_file.c_str());
- std::string ret = "";
- // Now try to open the archive.
- mz_zip_archive zip_archive;
- memset(&zip_archive, 0, sizeof(zip_archive));
- mz_bool status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), 0);
- if (!status)
- {
- ESP_LOGD(TAG, "mzip_zip_reader_init_file() failed!");
- return ret;
- }
- // Get and print information about each file in the archive.
- int numberoffiles = (int)mz_zip_reader_get_num_files(&zip_archive);
- LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Files to be extracted: " + to_string(numberoffiles));
- int sort_iter = 0;
- memset(&zip_archive, 0, sizeof(zip_archive));
- status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
- if (!status)
- {
- ESP_LOGD(TAG, "mzip_zip_reader_init_file() failed!");
- return ret;
- }
- void *pZip;
- size_t uncomp_size;
- char archive_filename[64];
- std::string directory = "";
- std::string temp_string = "";
- for (int i = 0; i < numberoffiles; i++)
- {
- mz_zip_archive_file_stat file_stat;
- mz_zip_reader_file_stat(&zip_archive, i, &file_stat);
- sprintf(archive_filename, file_stat.m_filename);
- if (!file_stat.m_is_directory)
- {
- // Try to extract all the files to the heap.
- pZip = mz_zip_reader_extract_file_to_heap(&zip_archive, archive_filename, &uncomp_size, 0);
- if (!pZip)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "mzip_zip_reader_extract_file_to_heap() failed on file " + string(archive_filename));
- mz_zip_reader_end(&zip_archive);
- return ret;
- }
- // Save to File.
- temp_string = std::string(archive_filename);
- ESP_LOGD(TAG, "Rohfilename: %s", temp_string.c_str());
- if (to_upper(temp_string) == "FIRMWARE.BIN")
- {
- temp_string = _target_bin + temp_string;
- ret = temp_string;
- }
- else
- {
- std::string _dir = get_directory(temp_string);
- if ((_dir == "config-initial") && !_initial_setup)
- {
- continue;
- }
- else
- {
- _dir = "config";
- std::string _s1 = "config-initial";
- find_replace(temp_string, _s1, _dir);
- }
- if (_dir.length() > 0)
- {
- temp_string = _main + temp_string;
- }
- else
- {
- temp_string = _html_tmp + temp_string;
- }
- }
- // files in the html folder shall be redirected to the temporary html folder
- if (temp_string.find(_html_final) == 0)
- {
- find_replace(temp_string, _html_final, _html_tmp);
- }
- string temp_filename = temp_string + TEMP_SUFFIX;
- ESP_LOGI(TAG, "File to extract: %s, Temp. Filename: %s", temp_string.c_str(), temp_filename.c_str());
- std::string folder = temp_filename.substr(0, temp_filename.find_last_of('/'));
- make_dir(folder);
- // extrahieren in zwischendatei
- delete_file(temp_filename);
- FILE *fpTargetFile = fopen(temp_filename.c_str(), "wb");
- uint writtenbytes = fwrite(pZip, 1, (uint)uncomp_size, fpTargetFile);
- fclose(fpTargetFile);
- bool isokay = true;
- if (writtenbytes == (uint)uncomp_size)
- {
- isokay = true;
- }
- else
- {
- isokay = false;
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ERROR in writting extracted file (function fwrite) extracted file \"" + string(archive_filename) + "\", size " + to_string(uncomp_size));
- }
- delete_file(temp_string);
- if (!isokay)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ERROR in fwrite \"" + string(archive_filename) + "\", size " + to_string(uncomp_size));
- }
- isokay = isokay && rename_file(temp_filename, temp_string);
- if (!isokay)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ERROR in Rename \"" + temp_filename + "\" to \"" + temp_string);
- }
- if (isokay)
- {
- LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Successfully extracted file \"" + string(archive_filename) + "\", size " + to_string(uncomp_size));
- }
- else
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ERROR in extracting file \"" + string(archive_filename) + "\", size " + to_string(uncomp_size));
- ret = "ERROR";
- }
- mz_free(pZip);
- }
- }
- // Close the archive, freeing any resources it was using
- mz_zip_reader_end(&zip_archive);
- ESP_LOGD(TAG, "Success.");
- return ret;
- }
- void unzip(std::string _in_zip_file, std::string _target_directory)
- {
- ESP_LOGD(TAG, "minizip.c version: %s", MZ_VERSION);
- ESP_LOGD(TAG, "Zipfile: %s", _in_zip_file.c_str());
- ESP_LOGD(TAG, "Target Dir: %s", _target_directory.c_str());
- // Now try to open the archive.
- mz_zip_archive zip_archive;
- memset(&zip_archive, 0, sizeof(zip_archive));
- mz_bool status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), 0);
- if (!status)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "mzip_zip_reader_init_file() failed!");
- return;
- }
- // Get and print information about each file in the archive.
- int numberoffiles = (int)mz_zip_reader_get_num_files(&zip_archive);
- void *pZip;
- size_t uncomp_size;
- char archive_filename[64];
- std::string temp_string;
- for (int sort_iter = 0; sort_iter < 2; sort_iter++)
- {
- memset(&zip_archive, 0, sizeof(zip_archive));
- status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
- if (!status)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "mzip_zip_reader_init_file() failed!");
- return;
- }
- for (int i = 0; i < numberoffiles; i++)
- {
- mz_zip_archive_file_stat file_stat;
- mz_zip_reader_file_stat(&zip_archive, i, &file_stat);
- sprintf(archive_filename, file_stat.m_filename);
- // Try to extract all the files to the heap.
- pZip = mz_zip_reader_extract_file_to_heap(&zip_archive, archive_filename, &uncomp_size, 0);
- if (!pZip)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "mzip_zip_reader_extract_file_to_heap() failed!");
- mz_zip_reader_end(&zip_archive);
- return;
- }
- // Save to File.
- temp_string = std::string(archive_filename);
- temp_string = _target_directory + temp_string;
- ESP_LOGD(TAG, "File to extract: %s", temp_string.c_str());
- FILE *fpTargetFile = fopen(temp_string.c_str(), "wb");
- fwrite(pZip, 1, (uint)uncomp_size, fpTargetFile);
- fclose(fpTargetFile);
- ESP_LOGD(TAG, "Successfully extracted file \"%s\", size %u", archive_filename, (uint)uncomp_size);
- // We're done.
- mz_free(pZip);
- }
- // Close the archive, freeing any resources it was using
- mz_zip_reader_end(&zip_archive);
- }
- ESP_LOGD(TAG, "Success.");
- }
- void file_server_register_uri(httpd_handle_t server, const char *base_path)
- {
- static struct file_server_data *server_data = NULL;
- /* Validate file storage base path */
- if (!base_path)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File server base_path not set");
- }
- if (server_data)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File server already started");
- }
- /* Allocate memory for server data */
- server_data = (file_server_data *)calloc(1, sizeof(struct file_server_data));
- if (!server_data)
- {
- LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocate memory for server data");
- }
- strlcpy(server_data->base_path, base_path, sizeof(server_data->base_path));
- /* URI handler for getting uploaded files */
- httpd_uri_t file_download = {
- .uri = "/fileserver*",
- .method = HTTP_GET,
- .handler = APPLY_BASIC_AUTH_FILTER(download_get_handler),
- .user_ctx = server_data,
- };
- httpd_register_uri_handler(server, &file_download);
- httpd_uri_t file_datafileact = {
- .uri = "/datafileact",
- .method = HTTP_GET,
- .handler = APPLY_BASIC_AUTH_FILTER(datafileact_get_full_handler),
- .user_ctx = server_data,
- };
- httpd_register_uri_handler(server, &file_datafileact);
- httpd_uri_t file_datafile_last_part_handle = {
- .uri = "/data",
- .method = HTTP_GET,
- .handler = APPLY_BASIC_AUTH_FILTER(datafileact_get_last_part_handler),
- .user_ctx = server_data,
- };
- httpd_register_uri_handler(server, &file_datafile_last_part_handle);
- httpd_uri_t file_logfileact = {
- .uri = "/logfileact",
- .method = HTTP_GET,
- .handler = APPLY_BASIC_AUTH_FILTER(logfileact_get_full_handler),
- .user_ctx = server_data,
- };
- httpd_register_uri_handler(server, &file_logfileact);
- httpd_uri_t file_logfile_last_part_handle = {
- .uri = "/log",
- .method = HTTP_GET,
- .handler = APPLY_BASIC_AUTH_FILTER(logfileact_get_last_part_handler),
- .user_ctx = server_data,
- };
- httpd_register_uri_handler(server, &file_logfile_last_part_handle);
- /* URI handler for uploading files to server */
- httpd_uri_t file_upload = {
- .uri = "/upload/*",
- .method = HTTP_POST,
- .handler = APPLY_BASIC_AUTH_FILTER(upload_post_handler),
- .user_ctx = server_data,
- };
- httpd_register_uri_handler(server, &file_upload);
- /* URI handler for deleting files from server */
- httpd_uri_t file_delete = {
- .uri = "/delete/*",
- .method = HTTP_POST,
- .handler = APPLY_BASIC_AUTH_FILTER(delete_post_handler),
- .user_ctx = server_data,
- };
- httpd_register_uri_handler(server, &file_delete);
- }
|