From 602c5c08666f04e9365790aaf4d4d7493d2356c8 Mon Sep 17 00:00:00 2001 From: cpq Date: Mon, 15 Feb 2021 14:42:55 +0000 Subject: [PATCH] Refactor mg_url_encode --- mongoose.c | 61 +++++++++++++++++++++--------------------------- mongoose.h | 12 +--------- src/event.h | 11 --------- src/http.c | 48 ++++++++++++++++++------------------- src/http.h | 1 + src/sock.c | 4 ++-- test/unit_test.c | 25 ++++++++++++++++++++ 7 files changed, 79 insertions(+), 83 deletions(-) diff --git a/mongoose.c b/mongoose.c index 9f6d5631..bb43e9df 100644 --- a/mongoose.c +++ b/mongoose.c @@ -956,34 +956,11 @@ struct dirent *readdir(DIR *d) { } #endif -static bool mg_is_safe(int c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || strchr("._-$,;~()/", c) != NULL; -} - -static int mg_url_encode(const char *s, char *buf, size_t len) { - int i, n = 0; - for (i = 0; s[i] != '\0'; i++) { - int c = *((const unsigned char *) (s + i)); - if ((size_t) n + 4 >= len) return 0; - if (mg_is_safe(c)) { - buf[n++] = s[i]; - } else { - buf[n++] = '%'; - mg_hex(&s[i], 1, &buf[n]); - n += 2; - } - } - return n; -} - static void printdirentry(struct mg_connection *c, const char *name, mg_stat_t *stp) { char size[64], mod[64], path[MG_PATH_MAX]; - int is_dir = S_ISDIR(stp->st_mode); + int is_dir = S_ISDIR(stp->st_mode), n = 0; const char *slash = is_dir ? "/" : ""; - // const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : ""; - int n = 0; if (is_dir) { snprintf(size, sizeof(size), "%s", "[DIR]"); @@ -999,7 +976,7 @@ static void printdirentry(struct mg_connection *c, const char *name, } } strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime)); - n = mg_url_encode(name, path, sizeof(path)); + n = mg_url_encode(name, strlen(name), path, sizeof(path)); mg_printf(c, " %s%s" "%s%s\n", @@ -1158,6 +1135,27 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, } #endif +static bool mg_is_url_safe(int c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~'; +} + +int mg_url_encode(const char *s, size_t sl, char *buf, size_t len) { + size_t i, n = 0; + for (i = 0; i < sl; i++) { + int c = *(unsigned char *) &s[i]; + if (n + 4 >= len) return 0; + if (mg_is_url_safe(c)) { + buf[n++] = s[i]; + } else { + buf[n++] = '%'; + mg_hex(&s[i], 1, &buf[n]); + n += 2; + } + } + return n; +} + void mg_http_creds(struct mg_http_message *hm, char *user, int userlen, char *pass, int passlen) { struct mg_str *v = mg_http_get_header(hm, "Authorization"); @@ -1295,11 +1293,7 @@ int mg_iobuf_resize(struct mg_iobuf *io, size_t new_size) { } int mg_iobuf_init(struct mg_iobuf *io, size_t size) { - int ok = 1; - io->buf = NULL; - io->len = io->size = 0; - if (size > 0) ok = mg_iobuf_resize(io, size); - return ok; + return mg_iobuf_resize(io, size); } size_t mg_iobuf_append(struct mg_iobuf *io, const void *buf, size_t len, @@ -1321,8 +1315,7 @@ size_t mg_iobuf_delete(struct mg_iobuf *io, size_t len) { } void mg_iobuf_free(struct mg_iobuf *io) { - free(io->buf); - mg_iobuf_init(io, 0); + mg_iobuf_resize(io, 0); } #ifdef MG_ENABLE_LINES @@ -2675,7 +2668,7 @@ static int ll_read(struct mg_connection *c, void *buf, int len, int *fail) { MG_SOCK_ERRNO, *fail)); if (n > 0 && c->is_hexdumping) { char *s = mg_hexdump(buf, n); - // LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "<-", n, s)); + LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "<-", n, s)); free(s); } return n; @@ -2691,7 +2684,7 @@ static int ll_write(struct mg_connection *c, const void *buf, int len, MG_SOCK_ERRNO)); if (n > 0 && c->is_hexdumping) { char *s = mg_hexdump(buf, len); - // LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "->", len, s)); + LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "->", len, s)); free(s); } return n; diff --git a/mongoose.h b/mongoose.h index d07c7c01..28fe71b0 100644 --- a/mongoose.h +++ b/mongoose.h @@ -568,17 +568,6 @@ void mg_hmac_sha1(const unsigned char *key, size_t key_len, struct mg_connection; typedef void (*mg_event_handler_t)(struct mg_connection *, int ev, void *ev_data, void *fn_data); -#if 0 -struct mg_fn { - struct mg_fn *next; - mg_event_handler_t fn; - void *fn_data; -}; - -void mg_fn_add(struct mg_connection *c, mg_event_handler_t fn, void *fn_data); -void mg_fn_del(struct mg_connection *c, mg_event_handler_t fn); -#endif - void mg_call(struct mg_connection *c, int ev, void *ev_data); void mg_error(struct mg_connection *c, const char *fmt, ...); @@ -722,6 +711,7 @@ struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); void mg_http_event_handler(struct mg_connection *c, int ev); int mg_http_get_var(const struct mg_str *, const char *name, char *, int); int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); +int mg_url_encode(const char *s, size_t n, char *buf, size_t len); void mg_http_creds(struct mg_http_message *, char *user, int, char *pass, int); bool mg_http_match_uri(const struct mg_http_message *, const char *glob); int mg_http_upload(struct mg_connection *, struct mg_http_message *hm, diff --git a/src/event.h b/src/event.h index 3879224c..0c788255 100644 --- a/src/event.h +++ b/src/event.h @@ -3,17 +3,6 @@ struct mg_connection; typedef void (*mg_event_handler_t)(struct mg_connection *, int ev, void *ev_data, void *fn_data); -#if 0 -struct mg_fn { - struct mg_fn *next; - mg_event_handler_t fn; - void *fn_data; -}; - -void mg_fn_add(struct mg_connection *c, mg_event_handler_t fn, void *fn_data); -void mg_fn_del(struct mg_connection *c, mg_event_handler_t fn); -#endif - void mg_call(struct mg_connection *c, int ev, void *ev_data); void mg_error(struct mg_connection *c, const char *fmt, ...); diff --git a/src/http.c b/src/http.c index f05555f2..e61a1ece 100644 --- a/src/http.c +++ b/src/http.c @@ -536,34 +536,11 @@ struct dirent *readdir(DIR *d) { } #endif -static bool mg_is_safe(int c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || strchr("._-$,;~()/", c) != NULL; -} - -static int mg_url_encode(const char *s, char *buf, size_t len) { - int i, n = 0; - for (i = 0; s[i] != '\0'; i++) { - int c = *((const unsigned char *) (s + i)); - if ((size_t) n + 4 >= len) return 0; - if (mg_is_safe(c)) { - buf[n++] = s[i]; - } else { - buf[n++] = '%'; - mg_hex(&s[i], 1, &buf[n]); - n += 2; - } - } - return n; -} - static void printdirentry(struct mg_connection *c, const char *name, mg_stat_t *stp) { char size[64], mod[64], path[MG_PATH_MAX]; - int is_dir = S_ISDIR(stp->st_mode); + int is_dir = S_ISDIR(stp->st_mode), n = 0; const char *slash = is_dir ? "/" : ""; - // const char *es = hm->uri.ptr[hm->uri.len - 1] != '/' ? "/" : ""; - int n = 0; if (is_dir) { snprintf(size, sizeof(size), "%s", "[DIR]"); @@ -579,7 +556,7 @@ static void printdirentry(struct mg_connection *c, const char *name, } } strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime)); - n = mg_url_encode(name, path, sizeof(path)); + n = mg_url_encode(name, strlen(name), path, sizeof(path)); mg_printf(c, " %s%s" "%s%s\n", @@ -738,6 +715,27 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm, } #endif +static bool mg_is_url_safe(int c) { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || c == '.' || c == '_' || c == '-' || c == '~'; +} + +int mg_url_encode(const char *s, size_t sl, char *buf, size_t len) { + size_t i, n = 0; + for (i = 0; i < sl; i++) { + int c = *(unsigned char *) &s[i]; + if (n + 4 >= len) return 0; + if (mg_is_url_safe(c)) { + buf[n++] = s[i]; + } else { + buf[n++] = '%'; + mg_hex(&s[i], 1, &buf[n]); + n += 2; + } + } + return n; +} + void mg_http_creds(struct mg_http_message *hm, char *user, int userlen, char *pass, int passlen) { struct mg_str *v = mg_http_get_header(hm, "Authorization"); diff --git a/src/http.h b/src/http.h index 3079db2b..e54c8bd7 100644 --- a/src/http.h +++ b/src/http.h @@ -44,6 +44,7 @@ struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); void mg_http_event_handler(struct mg_connection *c, int ev); int mg_http_get_var(const struct mg_str *, const char *name, char *, int); int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); +int mg_url_encode(const char *s, size_t n, char *buf, size_t len); void mg_http_creds(struct mg_http_message *, char *user, int, char *pass, int); bool mg_http_match_uri(const struct mg_http_message *, const char *glob); int mg_http_upload(struct mg_connection *, struct mg_http_message *hm, diff --git a/src/sock.c b/src/sock.c index f3e75055..da76a964 100644 --- a/src/sock.c +++ b/src/sock.c @@ -135,7 +135,7 @@ static int ll_read(struct mg_connection *c, void *buf, int len, int *fail) { MG_SOCK_ERRNO, *fail)); if (n > 0 && c->is_hexdumping) { char *s = mg_hexdump(buf, n); - // LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "<-", n, s)); + LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "<-", n, s)); free(s); } return n; @@ -151,7 +151,7 @@ static int ll_write(struct mg_connection *c, const void *buf, int len, MG_SOCK_ERRNO)); if (n > 0 && c->is_hexdumping) { char *s = mg_hexdump(buf, len); - // LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "->", len, s)); + LOG(LL_INFO, ("\n-- %lu %s %s %d\n%s--", c->id, c->label, "->", len, s)); free(s); } return n; diff --git a/test/unit_test.c b/test/unit_test.c index 8d8568d1..871a71d9 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -1124,6 +1124,31 @@ static void test_util(void) { ASSERT(strcmp(mg_hex("abc", 3, buf), "616263") == 0); ASSERT(mg_url_decode("a=%", 3, buf, sizeof(buf), 0) < 0); ASSERT(mg_url_decode("&&&a=%", 6, buf, sizeof(buf), 0) < 0); + + { + char buf[100]; + int n; + ASSERT((n = mg_url_encode("", 0, buf, sizeof(buf))) == 0); + ASSERT((n = mg_url_encode("a", 1, buf, 0)) == 0); + ASSERT((n = mg_url_encode("a", 1, buf, sizeof(buf))) == 1); + ASSERT(strncmp(buf, "a", n) == 0); + ASSERT((n = mg_url_encode("._-~", 4, buf, sizeof(buf))) == 4); + ASSERT(strncmp(buf, "._-~", n) == 0); + ASSERT((n = mg_url_encode("a@%>", 4, buf, sizeof(buf))) == 10); + ASSERT(strncmp(buf, "a%40%25%3e", n) == 0); + ASSERT((n = mg_url_encode("a@b.c", 5, buf, sizeof(buf))) == 7); + ASSERT(strncmp(buf, "a%40b.c", n) == 0); + } + + { + char buf[100], *s = buf; + mg_asprintf(&s, sizeof(buf), "%s", "%3d", 123); + ASSERT(s == buf); + ASSERT(strcmp(buf, "%3d") == 0); + mg_asprintf(&s, sizeof(buf), "%.*s", 7, "a%40b.c"); + ASSERT(s == buf); + ASSERT(strcmp(buf, "a%40b.c") == 0); + } } int main(void) {