From a419e16f26423da9aca6496a30ae83ae8e357e31 Mon Sep 17 00:00:00 2001 From: cpq Date: Sat, 26 Sep 2026 15:40:43 +0100 Subject: [PATCH] Remove MG_ENABLE_DIRLIST, add mg_http_serve_opts :: enable_dir_listing --- mongoose.c | 22 ++++++------ mongoose.h | 36 +++++--------------- src/arch_esp32.h | 4 --- src/arch_mcuxpresso.h | 4 --- src/arch_unix.h | 4 --- src/arch_win32.h | 4 --- src/config.h | 4 --- src/dash.c | 2 +- src/http.c | 20 +++++------ src/http.h | 16 +++++---- test/unit_test.c | 9 +++-- tutorials/stm32/nucleo-h563zi/minimal/main.c | 5 +-- 12 files changed, 47 insertions(+), 83 deletions(-) diff --git a/mongoose.c b/mongoose.c index bce4bd4c..8ce1ed15 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1536,7 +1536,7 @@ static void mg_serve_fs(struct mg_connection *c, struct mg_http_message *hm, memset(&o, 0, sizeof(o)); o.root_dir = root; o.fs = dash->upload_fs ? dash->upload_fs : &mg_fs_posix; - o.allow_delete = o.allow_upload = true; + o.enable_delete = o.enable_upload = o.enable_dir_listing = true; if (stream) mg_http_serve_upload(c, hm, &o); else mg_http_serve_dir(c, hm, &o); } @@ -4169,7 +4169,6 @@ struct printdirentrydata { size_t count; }; -#if MG_ENABLE_DIRLIST static void printdirentry(const char *name, void *userdata) { struct printdirentrydata *d = (struct printdirentrydata *) userdata; struct mg_fs *fs = d->opts->fs == NULL ? &mg_fs_posix : d->opts->fs; @@ -4220,7 +4219,6 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, memcpy(c->send.buf + off - 12, tmp, n); // Set content length c->is_resp = 0; // Mark response end } -#endif // Map requested URI to the file path (buf,len). Use root directory r. // r could be a path optionally followed by map: PATH,/PREFIX1=PATH1,... @@ -4304,15 +4302,15 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, if (flags < 0) { // Do nothing: the response has already been sent by uri_to_file_status() } else if (flags & MG_FS_DIR) { -#if MG_ENABLE_DIRLIST - listdir(c, hm, opts, path); -#else - mg_http_reply(c, 403, "", "Forbidden\n"); -#endif - } else if (opts->allow_delete && + if (opts->enable_dir_listing) { + listdir(c, hm, opts, path); + } else { + mg_http_reply(c, 403, "", "Forbidden\n"); + } + } else if (opts->enable_delete && mg_strcasecmp(hm->method, mg_str("DELETE")) == 0) { mg_http_reply(c, flags && fs->rm(path) ? 200 : 404, "", ""); - } else if (opts->allow_upload && + } else if (opts->enable_upload && (mg_strcasecmp(hm->method, mg_str("POST")) == 0 || mg_strcasecmp(hm->method, mg_str("PUT")) == 0)) { // Small or already fully buffered body. mg_http_serve_upload() handles @@ -4350,13 +4348,13 @@ static bool serve_upload_cb(struct mg_http_message *hm, struct mg_str *data, // buffered in memory. Companion to mg_http_serve_dir(): call this from // MG_EV_HTTP_HDRS, and keep calling mg_http_serve_dir() from MG_EV_HTTP_MSG // as before - it handles uploads too, for bodies this function skips. -// Does nothing unless opts->allow_upload is set, the method is POST or PUT, +// Does nothing unless opts->enable_upload is set, the method is POST or PUT, // and Content-Length is known and >= 2 * MG_IO_SIZE. void mg_http_serve_upload(struct mg_connection *c, struct mg_http_message *hm, const struct mg_http_serve_opts *opts) { char path[MG_PATH_MAX]; struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; - if (!opts->allow_upload) { + if (!opts->enable_upload) { // Not enabled, nothing to do } else if (mg_strcasecmp(hm->method, mg_str("POST")) != 0 && mg_strcasecmp(hm->method, mg_str("PUT")) != 0) { diff --git a/mongoose.h b/mongoose.h index f1d02ed3..e7e93b32 100644 --- a/mongoose.h +++ b/mongoose.h @@ -325,10 +325,6 @@ extern "C" { #define MG_ENABLE_POSIX_FS 1 #endif -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST 1 -#endif - #ifndef MG_OTA_ESP32_WDT_TIMEOUT_MS #define MG_OTA_ESP32_WDT_TIMEOUT_MS 10000U #endif @@ -436,10 +432,6 @@ static inline uint32_t mg_ota_esp32_state_set(uint32_t state) { #define MG_PATH_MAX 100 #endif -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST 0 -#endif - #ifndef MG_ENABLE_TCPIP #define MG_ENABLE_TCPIP 1 // Enable built-in TCP/IP stack #endif @@ -888,10 +880,6 @@ static inline int mg_mkdir(const char *path, mode_t mode) { #include #include -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST 1 -#endif - #ifndef MG_PATH_MAX #define MG_PATH_MAX FILENAME_MAX #endif @@ -1073,10 +1061,6 @@ typedef int socklen_t; #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR) #endif -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST 1 -#endif - #ifndef SIGPIPE #define SIGPIPE 0 #endif @@ -1361,10 +1345,6 @@ struct timeval { #define MG_ENABLE_WINSOCK 1 #endif -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST MG_ENABLE_LFS -#endif - #ifndef MG_ENABLE_CUSTOM_RANDOM #define MG_ENABLE_CUSTOM_RANDOM 0 #endif @@ -2685,8 +2665,9 @@ struct mg_http_serve_opts { const char *mime_types; // Additional MIME types: "ext1=type1,ext2=type2". NULL for defaults only const char *page404; // Path to a custom 404 page, e.g. "/404.html". NULL for built-in struct mg_fs *fs; // Filesystem to use. NULL defaults to POSIX - bool allow_delete; // Allow to DELETE files - bool allow_upload; // Allow to POST/PUT files + bool enable_delete; // Allow to DELETE files + bool enable_upload; // Allow to POST/PUT files + bool enable_dir_listing; // Enable directory listing }; // A single part of a multipart/form-data body, filled by mg_http_next_multipart(). @@ -2760,10 +2741,11 @@ struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url, // mg_http_listen(), mg_http_serve_file(), mg_http_reply(), mg_match() // Notes: // Call from an MG_EV_HTTP_MSG handler. The uri in hm is mapped under -// opts->root_dir. Directory listing depends on MG_ENABLE_DIRLIST; SSI uses -// opts->ssi_pattern when configured. opts->allow_delete enables DELETE; -// opts->allow_upload enables POST/PUT, writing the whole body to a file - -// see mg_http_serve_upload() to also stream big uploads without buffering. +// opts->root_dir. opts->enable_dir_listing enables directory listing; SSI +// uses opts->ssi_pattern when configured. opts->enable_delete enables +// DELETE; opts->enable_upload enables POST/PUT, writing the whole body to +// a file - see mg_http_serve_upload() to also stream big uploads without +// buffering. void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm, const struct mg_http_serve_opts *); @@ -2775,7 +2757,7 @@ void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm, // whole body. Optional companion to mg_http_serve_dir(): call this from // MG_EV_HTTP_HDRS with the same opts, and keep calling mg_http_serve_dir() // from MG_EV_HTTP_MSG as usual - it still handles uploads this function skips. -// Does nothing unless opts->allow_upload is set, the method is POST or PUT, +// Does nothing unless opts->enable_upload is set, the method is POST or PUT, // and Content-Length is known and big enough. void mg_http_serve_upload(struct mg_connection *, struct mg_http_message *hm, const struct mg_http_serve_opts *); diff --git a/src/arch_esp32.h b/src/arch_esp32.h index 3df95b45..df0f76b8 100644 --- a/src/arch_esp32.h +++ b/src/arch_esp32.h @@ -33,10 +33,6 @@ #define MG_ENABLE_POSIX_FS 1 #endif -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST 1 -#endif - #ifndef MG_OTA_ESP32_WDT_TIMEOUT_MS #define MG_OTA_ESP32_WDT_TIMEOUT_MS 10000U #endif diff --git a/src/arch_mcuxpresso.h b/src/arch_mcuxpresso.h index b0571c47..3955d697 100644 --- a/src/arch_mcuxpresso.h +++ b/src/arch_mcuxpresso.h @@ -27,10 +27,6 @@ #define MG_PATH_MAX 100 #endif -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST 0 -#endif - #ifndef MG_ENABLE_TCPIP #define MG_ENABLE_TCPIP 1 // Enable built-in TCP/IP stack #endif diff --git a/src/arch_unix.h b/src/arch_unix.h index ea5e4b60..f31d2ffa 100644 --- a/src/arch_unix.h +++ b/src/arch_unix.h @@ -50,10 +50,6 @@ #include #include -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST 1 -#endif - #ifndef MG_PATH_MAX #define MG_PATH_MAX FILENAME_MAX #endif diff --git a/src/arch_win32.h b/src/arch_win32.h index 613ff46a..5f5bb1ca 100644 --- a/src/arch_win32.h +++ b/src/arch_win32.h @@ -166,10 +166,6 @@ typedef int socklen_t; #define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR) #endif -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST 1 -#endif - #ifndef SIGPIPE #define SIGPIPE 0 #endif diff --git a/src/config.h b/src/config.h index f45b7b4b..79083c3a 100644 --- a/src/config.h +++ b/src/config.h @@ -82,10 +82,6 @@ #define MG_ENABLE_WINSOCK 1 #endif -#ifndef MG_ENABLE_DIRLIST -#define MG_ENABLE_DIRLIST MG_ENABLE_LFS -#endif - #ifndef MG_ENABLE_CUSTOM_RANDOM #define MG_ENABLE_CUSTOM_RANDOM 0 #endif diff --git a/src/dash.c b/src/dash.c index d17a66e1..57b1ecd0 100644 --- a/src/dash.c +++ b/src/dash.c @@ -561,7 +561,7 @@ static void mg_serve_fs(struct mg_connection *c, struct mg_http_message *hm, memset(&o, 0, sizeof(o)); o.root_dir = root; o.fs = dash->upload_fs ? dash->upload_fs : &mg_fs_posix; - o.allow_delete = o.allow_upload = true; + o.enable_delete = o.enable_upload = o.enable_dir_listing = true; if (stream) mg_http_serve_upload(c, hm, &o); else mg_http_serve_dir(c, hm, &o); } diff --git a/src/http.c b/src/http.c index 848c449a..ad58c3f8 100644 --- a/src/http.c +++ b/src/http.c @@ -679,7 +679,6 @@ struct printdirentrydata { size_t count; }; -#if MG_ENABLE_DIRLIST static void printdirentry(const char *name, void *userdata) { struct printdirentrydata *d = (struct printdirentrydata *) userdata; struct mg_fs *fs = d->opts->fs == NULL ? &mg_fs_posix : d->opts->fs; @@ -730,7 +729,6 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, memcpy(c->send.buf + off - 12, tmp, n); // Set content length c->is_resp = 0; // Mark response end } -#endif // Map requested URI to the file path (buf,len). Use root directory r. // r could be a path optionally followed by map: PATH,/PREFIX1=PATH1,... @@ -814,15 +812,15 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, if (flags < 0) { // Do nothing: the response has already been sent by uri_to_file_status() } else if (flags & MG_FS_DIR) { -#if MG_ENABLE_DIRLIST - listdir(c, hm, opts, path); -#else - mg_http_reply(c, 403, "", "Forbidden\n"); -#endif - } else if (opts->allow_delete && + if (opts->enable_dir_listing) { + listdir(c, hm, opts, path); + } else { + mg_http_reply(c, 403, "", "Forbidden\n"); + } + } else if (opts->enable_delete && mg_strcasecmp(hm->method, mg_str("DELETE")) == 0) { mg_http_reply(c, flags && fs->rm(path) ? 200 : 404, "", ""); - } else if (opts->allow_upload && + } else if (opts->enable_upload && (mg_strcasecmp(hm->method, mg_str("POST")) == 0 || mg_strcasecmp(hm->method, mg_str("PUT")) == 0)) { // Small or already fully buffered body. mg_http_serve_upload() handles @@ -860,13 +858,13 @@ static bool serve_upload_cb(struct mg_http_message *hm, struct mg_str *data, // buffered in memory. Companion to mg_http_serve_dir(): call this from // MG_EV_HTTP_HDRS, and keep calling mg_http_serve_dir() from MG_EV_HTTP_MSG // as before - it handles uploads too, for bodies this function skips. -// Does nothing unless opts->allow_upload is set, the method is POST or PUT, +// Does nothing unless opts->enable_upload is set, the method is POST or PUT, // and Content-Length is known and >= 2 * MG_IO_SIZE. void mg_http_serve_upload(struct mg_connection *c, struct mg_http_message *hm, const struct mg_http_serve_opts *opts) { char path[MG_PATH_MAX]; struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; - if (!opts->allow_upload) { + if (!opts->enable_upload) { // Not enabled, nothing to do } else if (mg_strcasecmp(hm->method, mg_str("POST")) != 0 && mg_strcasecmp(hm->method, mg_str("PUT")) != 0) { diff --git a/src/http.h b/src/http.h index aac3e99b..302c6173 100644 --- a/src/http.h +++ b/src/http.h @@ -32,8 +32,9 @@ struct mg_http_serve_opts { const char *mime_types; // Additional MIME types: "ext1=type1,ext2=type2". NULL for defaults only const char *page404; // Path to a custom 404 page, e.g. "/404.html". NULL for built-in struct mg_fs *fs; // Filesystem to use. NULL defaults to POSIX - bool allow_delete; // Allow to DELETE files - bool allow_upload; // Allow to POST/PUT files + bool enable_delete; // Allow to DELETE files + bool enable_upload; // Allow to POST/PUT files + bool enable_dir_listing; // Enable directory listing }; // A single part of a multipart/form-data body, filled by mg_http_next_multipart(). @@ -107,10 +108,11 @@ struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url, // mg_http_listen(), mg_http_serve_file(), mg_http_reply(), mg_match() // Notes: // Call from an MG_EV_HTTP_MSG handler. The uri in hm is mapped under -// opts->root_dir. Directory listing depends on MG_ENABLE_DIRLIST; SSI uses -// opts->ssi_pattern when configured. opts->allow_delete enables DELETE; -// opts->allow_upload enables POST/PUT, writing the whole body to a file - -// see mg_http_serve_upload() to also stream big uploads without buffering. +// opts->root_dir. opts->enable_dir_listing enables directory listing; SSI +// uses opts->ssi_pattern when configured. opts->enable_delete enables +// DELETE; opts->enable_upload enables POST/PUT, writing the whole body to +// a file - see mg_http_serve_upload() to also stream big uploads without +// buffering. void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm, const struct mg_http_serve_opts *); @@ -122,7 +124,7 @@ void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm, // whole body. Optional companion to mg_http_serve_dir(): call this from // MG_EV_HTTP_HDRS with the same opts, and keep calling mg_http_serve_dir() // from MG_EV_HTTP_MSG as usual - it still handles uploads this function skips. -// Does nothing unless opts->allow_upload is set, the method is POST or PUT, +// Does nothing unless opts->enable_upload is set, the method is POST or PUT, // and Content-Length is known and big enough. void mg_http_serve_upload(struct mg_connection *, struct mg_http_message *hm, const struct mg_http_serve_opts *); diff --git a/test/unit_test.c b/test/unit_test.c index 69d2fa1d..b5de3da6 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -833,7 +833,7 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data) { struct mg_http_serve_opts sopts; memset(&sopts, 0, sizeof(sopts)); sopts.root_dir = "./data"; - sopts.allow_upload = true; + sopts.enable_upload = true; mg_http_serve_upload(c, (struct mg_http_message *) ev_data, &sopts); } else if (ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; @@ -866,6 +866,7 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data) { memset(&sopts, 0, sizeof(sopts)); sopts.root_dir = "."; sopts.extra_headers = "A: B\r\nE: F\r\n"; + sopts.enable_dir_listing = true; mg_http_serve_dir(c, hm, &sopts); } else if (mg_match(hm->uri, mg_str("/servefile"), NULL)) { struct mg_http_serve_opts sopts; @@ -883,8 +884,8 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data) { sopts.root_dir = "./data"; sopts.ssi_pattern = "#.shtml"; sopts.extra_headers = "C: D\r\n"; - sopts.allow_delete = true; - sopts.allow_upload = true; + sopts.enable_delete = true; + sopts.enable_upload = true; mg_http_serve_dir(c, hm, &sopts); } } else if (ev == MG_EV_WS_OPEN) { @@ -3569,6 +3570,7 @@ static void eh7(struct mg_connection *c, int ev, void *ev_data) { memset(&sopts, 0, sizeof(sopts)); sopts.root_dir = "/"; sopts.fs = &mg_fs_packed; + sopts.enable_dir_listing = true; mg_mem_files = mg_packed_files; mg_http_serve_dir(c, hm, &sopts); } @@ -3738,6 +3740,7 @@ static void h7(struct mg_connection *c, int ev, void *ev_data) { struct mg_http_serve_opts opts; memset(&opts, 0, sizeof(opts)); opts.root_dir = "./data,/foo=./dirtest"; + opts.enable_dir_listing = true; mg_http_serve_dir(c, hm, &opts); } } diff --git a/tutorials/stm32/nucleo-h563zi/minimal/main.c b/tutorials/stm32/nucleo-h563zi/minimal/main.c index b94e82a2..40b4d999 100644 --- a/tutorials/stm32/nucleo-h563zi/minimal/main.c +++ b/tutorials/stm32/nucleo-h563zi/minimal/main.c @@ -48,8 +48,9 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) { } else if (mg_match(hm->uri, mg_str("/files/#"), NULL)) { struct mg_http_serve_opts opts = { .root_dir = "/files/=/fs/", - .allow_delete = true, - .allow_upload = true, + .enable_delete = true, + .enable_upload = true, + .enable_dir_listing = true, }; mg_http_serve_dir(c, hm, &opts); } else {