diff --git a/docs/c-api/util.h/intro.md b/docs/c-api/util.h/intro.md index d04619a1..73c4f792 100644 --- a/docs/c-api/util.h/intro.md +++ b/docs/c-api/util.h/intro.md @@ -22,6 +22,7 @@ items: - { name: mg_sock_to_str.md } - { name: mg_start_thread.md } - { name: mg_stat.md } + - { name: mg_url_encode.md } --- diff --git a/docs/c-api/util.h/mg_url_encode.md b/docs/c-api/util.h/mg_url_encode.md new file mode 100644 index 00000000..105ce947 --- /dev/null +++ b/docs/c-api/util.h/mg_url_encode.md @@ -0,0 +1,13 @@ +--- +title: "mg_url_encode()" +decl_name: "mg_url_encode" +symbol_kind: "func" +signature: | + struct mg_str mg_url_encode(const struct mg_str src); +--- + +URL-escape the specified string. +All non-printable characters are escaped, plus `._-$,;~()/`. +Input need not be NUL-terminated, but the returned string is. +Returned string is heap-allocated and must be free()'d. + diff --git a/mongoose.c b/mongoose.c index 3dfe789a..f3210df8 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7033,28 +7033,6 @@ static int mg_http_is_authorized(struct http_message *hm, #endif #if MG_ENABLE_DIRECTORY_LISTING -static size_t mg_url_encode(const char *src, size_t s_len, char *dst, - size_t dst_len) { - static const char *dont_escape = "._-$,;~()/"; - static const char *hex = "0123456789abcdef"; - size_t i = 0, j = 0; - - for (i = j = 0; dst_len > 0 && i < s_len && j + 2 < dst_len - 1; i++, j++) { - if (isalnum(*(const unsigned char *) (src + i)) || - strchr(dont_escape, *(const unsigned char *) (src + i)) != NULL) { - dst[j] = src[i]; - } else if (j + 3 < dst_len) { - dst[j] = '%'; - dst[j + 1] = hex[(*(const unsigned char *) (src + i)) >> 4]; - dst[j + 2] = hex[(*(const unsigned char *) (src + i)) & 0xf]; - j += 2; - } - } - - dst[j] = '\0'; - return j; -} - static void mg_escape(const char *src, char *dst, size_t dst_len) { size_t n = 0; while (*src != '\0' && n + 5 < dst_len) { @@ -7070,10 +7048,11 @@ static void mg_escape(const char *src, char *dst, size_t dst_len) { static void mg_print_dir_entry(struct mg_connection *nc, const char *file_name, cs_stat_t *stp) { - char size[64], mod[64], href[MG_MAX_PATH * 3], path[MG_MAX_PATH]; + char size[64], mod[64], path[MG_MAX_PATH]; int64_t fsize = stp->st_size; int is_dir = S_ISDIR(stp->st_mode); const char *slash = is_dir ? "/" : ""; + struct mg_str href; if (is_dir) { snprintf(size, sizeof(size), "%s", "[DIRECTORY]"); @@ -7094,12 +7073,13 @@ static void mg_print_dir_entry(struct mg_connection *nc, const char *file_name, } strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&stp->st_mtime)); mg_escape(file_name, path, sizeof(path)); - mg_url_encode(file_name, strlen(file_name), href, sizeof(href)); + href = mg_url_encode(mg_mk_str(file_name)); mg_printf_http_chunk(nc, "