From 894a16883307cb6d236473e2f6fa2311e3fde747 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka <valenok@gmail.com> Date: Wed, 15 Sep 2021 07:43:48 +0100 Subject: [PATCH] Get rid of fs->realpath --- mongoose.c | 140 +++++++++++++++++---------------------- mongoose.h | 47 ++++++++----- src/arch_freertos_lwip.h | 7 +- src/fs.h | 13 ++-- src/fs_packed.c | 13 +--- src/fs_posix.c | 18 +---- src/http.c | 106 +++++++++++++++-------------- src/http.h | 4 +- src/mqtt.h | 14 ++-- src/str.h | 4 +- src/util.c | 3 +- src/ws.h | 4 +- test/unit_test.c | 19 ++++-- 13 files changed, 191 insertions(+), 201 deletions(-) diff --git a/mongoose.c b/mongoose.c index 046dd1490..ff9d50ff1 100644 --- a/mongoose.c +++ b/mongoose.c @@ -431,13 +431,6 @@ const char *mg_unlist(size_t no) { } #endif -static char *packed_realpath(const char *path, char *resolved_path) { - if (resolved_path == NULL) resolved_path = (char *) malloc(strlen(path) + 1); - // while (*path == '.' || *path == '/') path++; - strcpy(resolved_path, path); - return resolved_path; -} - static int is_dir_prefix(const char *prefix, size_t n, const char *path) { return n < strlen(path) && memcmp(prefix, path, n) == 0 && path[n] == '/'; //(n == 0 || path[n] == MG_DIRSEP); @@ -515,9 +508,9 @@ static size_t packed_seek(void *fd, size_t offset) { return fp->pos; } -struct mg_fs mg_fs_packed = {packed_realpath, packed_stat, packed_list, - packed_open, packed_close, packed_read, - packed_write, packed_seek}; +struct mg_fs mg_fs_packed = {packed_stat, packed_list, packed_open, + packed_close, packed_read, packed_write, + packed_seek}; #ifdef MG_ENABLE_LINES #line 1 "src/fs_posix.c" @@ -525,19 +518,6 @@ struct mg_fs mg_fs_packed = {packed_realpath, packed_stat, packed_list, #if defined(FOPEN_MAX) -static char *posix_realpath(const char *path, char *resolved_path) { -#ifdef _WIN32 - return _fullpath(resolved_path, path, _MAX_PATH); -#elif MG_ARCH == MG_ARCH_ESP32 || MG_ARCH == MG_ARCH_ESP8266 || \ - MG_ARCH == MG_ARCH_FREERTOS_TCP || MG_ARCH == MG_ARCH_FREERTOS_LWIP - if (resolved_path == NULL) resolved_path = malloc(strlen(path) + 1); - strcpy(resolved_path, path); - return resolved_path; -#else - return realpath(path, resolved_path); -#endif -} - static int posix_stat(const char *path, size_t *size, time_t *mtime) { #ifdef _WIN32 struct _stati64 st; @@ -762,9 +742,8 @@ static size_t posix_seek(void *fd, size_t offset) { } #endif -struct mg_fs mg_fs_posix = {posix_realpath, posix_stat, posix_list, - posix_open, posix_close, posix_read, - posix_write, posix_seek}; +struct mg_fs mg_fs_posix = {posix_stat, posix_list, posix_open, posix_close, + posix_read, posix_write, posix_seek}; #ifdef MG_ENABLE_LINES #line 1 "src/http.c" @@ -1458,49 +1437,50 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, memcpy(c->send.buf + off - 10, tmp, n); // Set content length } +static void remove_double_dots(char *s) { + char *p = s; + while (*s != '\0') { + *p++ = *s++; + if (s[-1] == '/' || s[-1] == '\\') { + while (s[0] != '\0') { + if (s[0] == '/' || s[0] == '\\') { + s++; + } else if (s[0] == '.' && s[1] == '.') { + s += 2; + } else { + break; + } + } + } + } + *p = '\0'; +} + +// Resolve requested file into `path` and return its fs->stat() result static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm, - struct mg_http_serve_opts *opts, char *root_dir, - size_t rlen, char *path, size_t plen) { + struct mg_http_serve_opts *opts, char *path, + size_t path_size) { struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; int flags = 0, tmp; - if (fs->realpath(opts->root_dir, root_dir) == NULL) { - LOG(LL_ERROR, ("realpath(%s): %d", opts->root_dir, errno)); - mg_http_reply(c, 400, "", "Bad web root [%s]\n", opts->root_dir); - } else if (!(fs->stat(root_dir, NULL, NULL) & MG_FS_DIR)) { - mg_http_reply(c, 400, "", "Invalid web root [%s]\n", root_dir); - } else { - // NOTE(lsm): Xilinx snprintf does not 0-terminate the destination for - // the %.*s specifier, if the length is zero. Make sure hm->uri.len > 0 - size_t n1 = strlen(root_dir), n2; - // Temporarily append URI to the root_dir: that is the unresolved path - mg_url_decode(hm->uri.ptr, hm->uri.len, root_dir + n1, rlen - n1, 0); - root_dir[rlen - 1] = '\0'; - n2 = strlen(root_dir); - while (n2 > 0 && root_dir[n2 - 1] == '/') root_dir[--n2] = 0; - // Try to resolve it... - if (fs->realpath(root_dir, path) == NULL || - (flags = fs->stat(path, NULL, NULL)) == 0) { - mg_http_reply(c, 404, "", "Not found\n"); + // Append URI to the root_dir, and sanitize it + size_t n = (size_t) snprintf(path, path_size, "%s", opts->root_dir); + if (n > path_size) n = path_size; + mg_url_decode(hm->uri.ptr, hm->uri.len, path + n, path_size - n, 0); + path[path_size - 1] = '\0'; // Double-check + remove_double_dots(path); + n = strlen(path); + while (n > 0 && path[n - 1] == '/') path[--n] = 0; // Strip trailing slashes + flags = fs->stat(path, NULL, NULL); // Does it exist? + if (flags == 0) { + mg_http_reply(c, 404, "", "Not found\n"); // Does not exist, doh + } else if (flags & MG_FS_DIR) { + if (((snprintf(path + n, path_size - n, "/index.html") > 0 && + (tmp = fs->stat(path, NULL, NULL)) != 0) || + (snprintf(path + n, path_size - n, "/index.shtml") > 0 && + (tmp = fs->stat(path, NULL, NULL)) != 0))) { + flags = tmp; } else { - // Path is resolved successfully. It it is a directory, try to - // serve index.html in it - root_dir[n1] = '\0'; // Restore root_dir - remove appended URI - n2 = strlen(path); // Memorise path length - if ((flags & MG_FS_DIR) && - ((snprintf(path + n2, plen - n2, "/index.html") > 0 && - (tmp = fs->stat(path, NULL, NULL)) != 0) || - (snprintf(path + n2, plen - n2, "/index.shtml") > 0 && - (tmp = fs->stat(path, NULL, NULL)) != 0))) { - flags = tmp; - } else { - path[n2] = '\0'; // Remove appended index file name - } - } - // Check that the resolved file is located inside root directory - if (strlen(path) < n1 || memcmp(root_dir, path, n1) != 0) { - mg_http_reply(c, 404, "", "Invalid URI [%.*s]\n", (int) hm->uri.len, - hm->uri.ptr); - flags = 0; + path[n] = '\0'; // Remove appended index file name } } return flags; @@ -1508,19 +1488,22 @@ static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm, void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, struct mg_http_serve_opts *opts) { - char root[MG_PATH_MAX] = "", path[sizeof(root)] = ""; - int flags = uri_to_path(c, hm, opts, root, sizeof(root), path, sizeof(path)); - - if (flags == 0) return; - // LOG(LL_DEBUG, ("root [%s], path [%s] %d", root, path, flags)); - if (flags & MG_FS_DIR) { - listdir(c, hm, opts, path); - } else if (opts->ssi_pattern != NULL && - mg_globmatch(opts->ssi_pattern, strlen(opts->ssi_pattern), path, - strlen(path))) { - mg_http_serve_ssi(c, root, path); + char path[MG_PATH_MAX] = ""; + const char *sp = opts->ssi_pattern; + struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; + if ((fs->stat(opts->root_dir, NULL, NULL) & MG_FS_DIR) == 0) { + mg_http_reply(c, 400, "", "Invalid web root [%s]\n", opts->root_dir); } else { - mg_http_serve_file(c, hm, path, opts); + int flags = uri_to_path(c, hm, opts, path, sizeof(path)); + if (flags == 0) return; + LOG(LL_DEBUG, ("%.*s %s %d", (int) hm->uri.len, hm->uri.ptr, path, flags)); + if (flags & MG_FS_DIR) { + listdir(c, hm, opts, path); + } else if (sp != NULL && mg_globmatch(sp, strlen(sp), path, strlen(path))) { + mg_http_serve_ssi(c, opts->root_dir, path); + } else { + mg_http_serve_file(c, hm, path, opts); + } } } @@ -4213,9 +4196,10 @@ bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) { i++, j++; } else if (i < n1 && (s1[i] == '*' || s1[i] == '#')) { ni = i, nj = j + 1, i++; - } else if (nj > 0 && nj <= n2 && (s1[i - 1] == '#' || s2[j] != '/')) { + } else if (nj > 0 && nj <= n2 && (s1[ni] == '#' || s2[j] != '/')) { i = ni, j = nj; } else { + // printf(">>: [%s] [%s] %d %d %d %d\n", s1, s2, i, j, ni, nj); return false; } } diff --git a/mongoose.h b/mongoose.h index 59c89101a..b2b2fadf4 100644 --- a/mongoose.h +++ b/mongoose.h @@ -214,13 +214,14 @@ struct timeval { #include <lwip/sockets.h> #if LWIP_SOCKET != 1 -// Sockets support disabled in LWIP by default +// Sockets support disabled in LWIP by default #error Set LWIP_SOCKET variable to 1 (in lwipopts.h) #endif #if LWIP_POSIX_SOCKETS_IO_NAMES != 0 -// LWIP_POSIX_SOCKETS_IO_NAMES must be disabled in posix-compatible OS enviroment -// (freertos mimics to one) otherwise names like `read` and `write` conflict +// LWIP_POSIX_SOCKETS_IO_NAMES must be disabled in posix-compatible OS +// enviroment (freertos mimics to one) otherwise names like `read` and `write` +// conflict #error LWIP_POSIX_SOCKETS_IO_NAMES must be set to 0 (in lwipopts.h) for FreeRTOS #endif @@ -467,8 +468,8 @@ static __inline struct tm *localtime_r(time_t *t, struct tm *tm) { #include <string.h> struct mg_str { - const char *ptr; - size_t len; + const char *ptr; // Pointer to string data + size_t len; // String len }; #define MG_NULL_STR \ @@ -596,13 +597,25 @@ enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 }; // Filesystem API functions struct mg_fs { - char *(*realpath)(const char *path, char *resolved_path); + // Return MG_FS_* flags, and populate file size and modification time int (*stat)(const char *path, size_t *size, time_t *mtime); + + // Enumerates objects in directory void (*list)(const char *path, void (*fn)(const char *, void *), void *); + + // Open file struct mg_fd *(*open)(const char *path, int flags); + + // Close file void (*close)(struct mg_fd *fd); + + // Read file size_t (*read)(void *fd, void *buf, size_t len); + + // Write file size_t (*write)(void *fd, const void *buf, size_t len); + + // Seek file size_t (*seek)(void *fd, size_t offset); }; @@ -786,8 +799,8 @@ void mg_mgr_wakeup(struct mg_connection *pipe); struct mg_http_header { - struct mg_str name; - struct mg_str value; + struct mg_str name; // Header name + struct mg_str value; // Header value }; struct mg_http_message { @@ -873,8 +886,8 @@ void mg_tls_handshake(struct mg_connection *); struct mg_ws_message { - struct mg_str data; - uint8_t flags; // Websocket message flags + struct mg_str data; // Websocket message data + uint8_t flags; // Websocket message flags }; struct mg_connection *mg_ws_connect(struct mg_mgr *, const char *url, @@ -917,13 +930,13 @@ int mg_sntp_parse(const unsigned char *buf, size_t len, struct timeval *tv); #define MQTT_SET_QOS(flags, qos) (flags) = ((flags) & ~0x6) | ((qos) << 1) struct mg_mqtt_opts { - struct mg_str client_id; - struct mg_str will_topic; - struct mg_str will_message; - uint8_t qos; // Quality of service - bool will_retain; // Retain last will - bool clean; // Use clean session, 0 or 1 - uint16_t keepalive; // Keep-alive timer in seconds + struct mg_str client_id; // Client ID + struct mg_str will_topic; // Will topic + struct mg_str will_message; // Will message + uint8_t qos; // Quality of service + bool will_retain; // Retain last will + bool clean; // Use clean session, 0 or 1 + uint16_t keepalive; // Keep-alive timer in seconds }; struct mg_mqtt_message { diff --git a/src/arch_freertos_lwip.h b/src/arch_freertos_lwip.h index 56213b972..88d08ff4d 100644 --- a/src/arch_freertos_lwip.h +++ b/src/arch_freertos_lwip.h @@ -24,13 +24,14 @@ struct timeval { #include <lwip/sockets.h> #if LWIP_SOCKET != 1 -// Sockets support disabled in LWIP by default +// Sockets support disabled in LWIP by default #error Set LWIP_SOCKET variable to 1 (in lwipopts.h) #endif #if LWIP_POSIX_SOCKETS_IO_NAMES != 0 -// LWIP_POSIX_SOCKETS_IO_NAMES must be disabled in posix-compatible OS enviroment -// (freertos mimics to one) otherwise names like `read` and `write` conflict +// LWIP_POSIX_SOCKETS_IO_NAMES must be disabled in posix-compatible OS +// enviroment (freertos mimics to one) otherwise names like `read` and `write` +// conflict #error LWIP_POSIX_SOCKETS_IO_NAMES must be set to 0 (in lwipopts.h) for FreeRTOS #endif diff --git a/src/fs.h b/src/fs.h index 8afb2f56d..ecd179f54 100644 --- a/src/fs.h +++ b/src/fs.h @@ -5,15 +5,16 @@ enum { MG_FS_READ = 1, MG_FS_WRITE = 2, MG_FS_DIR = 4 }; // Filesystem API functions +// stat() returns MG_FS_* flags and populates file size and modification time +// list() calls fn() for every directory entry, allowing to list a directory struct mg_fs { - char *(*realpath)(const char *path, char *resolved_path); int (*stat)(const char *path, size_t *size, time_t *mtime); void (*list)(const char *path, void (*fn)(const char *, void *), void *); - struct mg_fd *(*open)(const char *path, int flags); - void (*close)(struct mg_fd *fd); - size_t (*read)(void *fd, void *buf, size_t len); - size_t (*write)(void *fd, const void *buf, size_t len); - size_t (*seek)(void *fd, size_t offset); + struct mg_fd *(*open)(const char *path, int flags); // Open file + void (*close)(struct mg_fd *fd); // Close file + size_t (*read)(void *fd, void *buf, size_t len); // Read file + size_t (*write)(void *fd, const void *buf, size_t len); // Write file + size_t (*seek)(void *fd, size_t offset); // Set file position }; // File descriptor diff --git a/src/fs_packed.c b/src/fs_packed.c index 905312456..23a21a205 100644 --- a/src/fs_packed.c +++ b/src/fs_packed.c @@ -20,13 +20,6 @@ const char *mg_unlist(size_t no) { } #endif -static char *packed_realpath(const char *path, char *resolved_path) { - if (resolved_path == NULL) resolved_path = (char *) malloc(strlen(path) + 1); - // while (*path == '.' || *path == '/') path++; - strcpy(resolved_path, path); - return resolved_path; -} - static int is_dir_prefix(const char *prefix, size_t n, const char *path) { return n < strlen(path) && memcmp(prefix, path, n) == 0 && path[n] == '/'; //(n == 0 || path[n] == MG_DIRSEP); @@ -104,6 +97,6 @@ static size_t packed_seek(void *fd, size_t offset) { return fp->pos; } -struct mg_fs mg_fs_packed = {packed_realpath, packed_stat, packed_list, - packed_open, packed_close, packed_read, - packed_write, packed_seek}; +struct mg_fs mg_fs_packed = {packed_stat, packed_list, packed_open, + packed_close, packed_read, packed_write, + packed_seek}; diff --git a/src/fs_posix.c b/src/fs_posix.c index 308a62e2c..beb5c0d2c 100644 --- a/src/fs_posix.c +++ b/src/fs_posix.c @@ -1,19 +1,6 @@ #include "fs.h" #if defined(FOPEN_MAX) -static char *posix_realpath(const char *path, char *resolved_path) { -#ifdef _WIN32 - return _fullpath(resolved_path, path, _MAX_PATH); -#elif MG_ARCH == MG_ARCH_ESP32 || MG_ARCH == MG_ARCH_ESP8266 || \ - MG_ARCH == MG_ARCH_FREERTOS_TCP || MG_ARCH == MG_ARCH_FREERTOS_LWIP - if (resolved_path == NULL) resolved_path = malloc(strlen(path) + 1); - strcpy(resolved_path, path); - return resolved_path; -#else - return realpath(path, resolved_path); -#endif -} - static int posix_stat(const char *path, size_t *size, time_t *mtime) { #ifdef _WIN32 struct _stati64 st; @@ -238,6 +225,5 @@ static size_t posix_seek(void *fd, size_t offset) { } #endif -struct mg_fs mg_fs_posix = {posix_realpath, posix_stat, posix_list, - posix_open, posix_close, posix_read, - posix_write, posix_seek}; +struct mg_fs mg_fs_posix = {posix_stat, posix_list, posix_open, posix_close, + posix_read, posix_write, posix_seek}; diff --git a/src/http.c b/src/http.c index d11811967..d8d882ab7 100644 --- a/src/http.c +++ b/src/http.c @@ -687,49 +687,50 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm, memcpy(c->send.buf + off - 10, tmp, n); // Set content length } +static void remove_double_dots(char *s) { + char *p = s; + while (*s != '\0') { + *p++ = *s++; + if (s[-1] == '/' || s[-1] == '\\') { + while (s[0] != '\0') { + if (s[0] == '/' || s[0] == '\\') { + s++; + } else if (s[0] == '.' && s[1] == '.') { + s += 2; + } else { + break; + } + } + } + } + *p = '\0'; +} + +// Resolve requested file into `path` and return its fs->stat() result static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm, - struct mg_http_serve_opts *opts, char *root_dir, - size_t rlen, char *path, size_t plen) { + struct mg_http_serve_opts *opts, char *path, + size_t path_size) { struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; int flags = 0, tmp; - if (fs->realpath(opts->root_dir, root_dir) == NULL) { - LOG(LL_ERROR, ("realpath(%s): %d", opts->root_dir, errno)); - mg_http_reply(c, 400, "", "Bad web root [%s]\n", opts->root_dir); - } else if (!(fs->stat(root_dir, NULL, NULL) & MG_FS_DIR)) { - mg_http_reply(c, 400, "", "Invalid web root [%s]\n", root_dir); - } else { - // NOTE(lsm): Xilinx snprintf does not 0-terminate the destination for - // the %.*s specifier, if the length is zero. Make sure hm->uri.len > 0 - size_t n1 = strlen(root_dir), n2; - // Temporarily append URI to the root_dir: that is the unresolved path - mg_url_decode(hm->uri.ptr, hm->uri.len, root_dir + n1, rlen - n1, 0); - root_dir[rlen - 1] = '\0'; - n2 = strlen(root_dir); - while (n2 > 0 && root_dir[n2 - 1] == '/') root_dir[--n2] = 0; - // Try to resolve it... - if (fs->realpath(root_dir, path) == NULL || - (flags = fs->stat(path, NULL, NULL)) == 0) { - mg_http_reply(c, 404, "", "Not found\n"); + // Append URI to the root_dir, and sanitize it + size_t n = (size_t) snprintf(path, path_size, "%s", opts->root_dir); + if (n > path_size) n = path_size; + mg_url_decode(hm->uri.ptr, hm->uri.len, path + n, path_size - n, 0); + path[path_size - 1] = '\0'; // Double-check + remove_double_dots(path); + n = strlen(path); + while (n > 0 && path[n - 1] == '/') path[--n] = 0; // Strip trailing slashes + flags = fs->stat(path, NULL, NULL); // Does it exist? + if (flags == 0) { + mg_http_reply(c, 404, "", "Not found\n"); // Does not exist, doh + } else if (flags & MG_FS_DIR) { + if (((snprintf(path + n, path_size - n, "/index.html") > 0 && + (tmp = fs->stat(path, NULL, NULL)) != 0) || + (snprintf(path + n, path_size - n, "/index.shtml") > 0 && + (tmp = fs->stat(path, NULL, NULL)) != 0))) { + flags = tmp; } else { - // Path is resolved successfully. It it is a directory, try to - // serve index.html in it - root_dir[n1] = '\0'; // Restore root_dir - remove appended URI - n2 = strlen(path); // Memorise path length - if ((flags & MG_FS_DIR) && - ((snprintf(path + n2, plen - n2, "/index.html") > 0 && - (tmp = fs->stat(path, NULL, NULL)) != 0) || - (snprintf(path + n2, plen - n2, "/index.shtml") > 0 && - (tmp = fs->stat(path, NULL, NULL)) != 0))) { - flags = tmp; - } else { - path[n2] = '\0'; // Remove appended index file name - } - } - // Check that the resolved file is located inside root directory - if (strlen(path) < n1 || memcmp(root_dir, path, n1) != 0) { - mg_http_reply(c, 404, "", "Invalid URI [%.*s]\n", (int) hm->uri.len, - hm->uri.ptr); - flags = 0; + path[n] = '\0'; // Remove appended index file name } } return flags; @@ -737,19 +738,22 @@ static int uri_to_path(struct mg_connection *c, struct mg_http_message *hm, void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, struct mg_http_serve_opts *opts) { - char root[MG_PATH_MAX] = "", path[sizeof(root)] = ""; - int flags = uri_to_path(c, hm, opts, root, sizeof(root), path, sizeof(path)); - - if (flags == 0) return; - // LOG(LL_DEBUG, ("root [%s], path [%s] %d", root, path, flags)); - if (flags & MG_FS_DIR) { - listdir(c, hm, opts, path); - } else if (opts->ssi_pattern != NULL && - mg_globmatch(opts->ssi_pattern, strlen(opts->ssi_pattern), path, - strlen(path))) { - mg_http_serve_ssi(c, root, path); + char path[MG_PATH_MAX] = ""; + const char *sp = opts->ssi_pattern; + struct mg_fs *fs = opts->fs == NULL ? &mg_fs_posix : opts->fs; + if ((fs->stat(opts->root_dir, NULL, NULL) & MG_FS_DIR) == 0) { + mg_http_reply(c, 400, "", "Invalid web root [%s]\n", opts->root_dir); } else { - mg_http_serve_file(c, hm, path, opts); + int flags = uri_to_path(c, hm, opts, path, sizeof(path)); + if (flags == 0) return; + LOG(LL_DEBUG, ("%.*s %s %d", (int) hm->uri.len, hm->uri.ptr, path, flags)); + if (flags & MG_FS_DIR) { + listdir(c, hm, opts, path); + } else if (sp != NULL && mg_globmatch(sp, strlen(sp), path, strlen(path))) { + mg_http_serve_ssi(c, opts->root_dir, path); + } else { + mg_http_serve_file(c, hm, path, opts); + } } } diff --git a/src/http.h b/src/http.h index a9ffbad19..d65019e12 100644 --- a/src/http.h +++ b/src/http.h @@ -6,8 +6,8 @@ #include "str.h" struct mg_http_header { - struct mg_str name; - struct mg_str value; + struct mg_str name; // Header name + struct mg_str value; // Header value }; struct mg_http_message { diff --git a/src/mqtt.h b/src/mqtt.h index 8f88cc720..29c1fecf6 100644 --- a/src/mqtt.h +++ b/src/mqtt.h @@ -23,13 +23,13 @@ #define MQTT_SET_QOS(flags, qos) (flags) = ((flags) & ~0x6) | ((qos) << 1) struct mg_mqtt_opts { - struct mg_str client_id; - struct mg_str will_topic; - struct mg_str will_message; - uint8_t qos; // Quality of service - bool will_retain; // Retain last will - bool clean; // Use clean session, 0 or 1 - uint16_t keepalive; // Keep-alive timer in seconds + struct mg_str client_id; // Client ID + struct mg_str will_topic; // Will topic + struct mg_str will_message; // Will message + uint8_t qos; // Quality of service + bool will_retain; // Retain last will + bool clean; // Use clean session, 0 or 1 + uint16_t keepalive; // Keep-alive timer in seconds }; struct mg_mqtt_message { diff --git a/src/str.h b/src/str.h index 3d9633bf4..80a995b1e 100644 --- a/src/str.h +++ b/src/str.h @@ -4,8 +4,8 @@ #include <string.h> struct mg_str { - const char *ptr; - size_t len; + const char *ptr; // Pointer to string data + size_t len; // String len }; #define MG_NULL_STR \ diff --git a/src/util.c b/src/util.c index 8e3626a87..f070939f1 100644 --- a/src/util.c +++ b/src/util.c @@ -86,9 +86,10 @@ bool mg_globmatch(const char *s1, size_t n1, const char *s2, size_t n2) { i++, j++; } else if (i < n1 && (s1[i] == '*' || s1[i] == '#')) { ni = i, nj = j + 1, i++; - } else if (nj > 0 && nj <= n2 && (s1[i - 1] == '#' || s2[j] != '/')) { + } else if (nj > 0 && nj <= n2 && (s1[ni] == '#' || s2[j] != '/')) { i = ni, j = nj; } else { + // printf(">>: [%s] [%s] %d %d %d %d\n", s1, s2, i, j, ni, nj); return false; } } diff --git a/src/ws.h b/src/ws.h index a5ab1cc06..a2ae41578 100644 --- a/src/ws.h +++ b/src/ws.h @@ -10,8 +10,8 @@ #include "http.h" struct mg_ws_message { - struct mg_str data; - uint8_t flags; // Websocket message flags + struct mg_str data; // Websocket message data + uint8_t flags; // Websocket message flags }; struct mg_connection *mg_ws_connect(struct mg_mgr *, const char *url, diff --git a/test/unit_test.c b/test/unit_test.c index f3f8c2b9c..8bdfab228 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -36,6 +36,18 @@ static void test_globmatch(void) { ASSERT(mg_globmatch("/api/*", 6, "/api/foo", 8) == 1); ASSERT(mg_globmatch("/api/*", 6, "/api/log/static", 15) == 0); ASSERT(mg_globmatch("/api/#", 6, "/api/log/static", 15) == 1); + ASSERT(mg_globmatch("#.shtml", 7, "/ssi/index.shtml", 16) == 1); + ASSERT(mg_globmatch("#.c", 3, ".c", 2) == 1); + ASSERT(mg_globmatch("abc", 3, "ab", 2) == 0); + ASSERT(mg_globmatch("#.c", 3, "a.c", 3) == 1); + ASSERT(mg_globmatch("#.c", 3, "..c", 3) == 1); + ASSERT(mg_globmatch("#.c", 3, "/.c", 3) == 1); + ASSERT(mg_globmatch("#.c", 3, "//a.c", 5) == 1); + ASSERT(mg_globmatch("#.c", 3, "x/a.c", 5) == 1); + ASSERT(mg_globmatch("#.c", 3, "./a.c", 5) == 1); + ASSERT(mg_globmatch("#.shtml", 7, "./ssi/index.shtml", 17) == 1); + ASSERT(mg_globmatch("#aa#bb#", 7, "caabba", 6) == 1); + ASSERT(mg_globmatch("#aa#bb#", 7, "caabxa", 6) == 0); } static void test_commalist(void) { @@ -575,12 +587,7 @@ static void test_http_server(void) { } ASSERT(fetch(&mgr, buf, url, "GET /badroot HTTP/1.0\r\n\n") == 400); -#if MG_ARCH == MG_ARCH_WIN32 - ASSERT(cmpbody(buf, "Invalid web root [Z:\\BAAADDD!]\n") == 0); -#else - // LOG(LL_INFO, ("--> [%s]", buf)); - ASSERT(cmpbody(buf, "Bad web root [/BAAADDD!]\n") == 0); -#endif + ASSERT(cmpbody(buf, "Invalid web root [/BAAADDD!]\n") == 0); { char *data = mg_file_read("./test/data/ca.pem", NULL); -- GitLab