From 1bb98e5e8ee183c2ba9f234ee7a4561b3b97fc2d Mon Sep 17 00:00:00 2001 From: Sergey Lyubka <valenok@gmail.com> Date: Fri, 25 Apr 2014 18:04:24 +0100 Subject: [PATCH] Exported mg_websocket_printf(), mg_url_encode(). Added unit test for mg_url_encode() --- examples/unit_test.c | 12 +++++++++ mongoose.c | 59 +++++++++++++++++++++++++------------------- mongoose.h | 5 ++++ 3 files changed, 51 insertions(+), 25 deletions(-) diff --git a/examples/unit_test.c b/examples/unit_test.c index 3575e7de5..64e350cc6 100644 --- a/examples/unit_test.c +++ b/examples/unit_test.c @@ -271,6 +271,17 @@ static const char *test_url_decode(void) { return NULL; } +static const char *test_url_encode(void) { + char buf[100]; + ASSERT(mg_url_encode("", 0, buf, sizeof(buf)) == 0); + ASSERT(buf[0] == '\0'); + ASSERT(mg_url_encode("foo", 3, buf, sizeof(buf)) == 3); + ASSERT(strcmp(buf, "foo") == 0); + ASSERT(mg_url_encode("f o", 3, buf, sizeof(buf)) == 5); + ASSERT(strcmp(buf, "f%20o") == 0); + return NULL; +} + static const char *test_to64(void) { ASSERT(to64("0") == 0); ASSERT(to64("") == 0); @@ -498,6 +509,7 @@ static const char *run_all_tests(void) { RUN_TEST(test_parse_http_message); RUN_TEST(test_to64); RUN_TEST(test_url_decode); + RUN_TEST(test_url_encode); RUN_TEST(test_base64_encode); RUN_TEST(test_mg_parse_header); RUN_TEST(test_get_var); diff --git a/mongoose.c b/mongoose.c index bd89ac15e..97e15038a 100644 --- a/mongoose.c +++ b/mongoose.c @@ -3065,24 +3065,25 @@ static int scan_directory(struct connection *conn, const char *dir, return arr_ind; } -static void mg_url_encode(const char *src, char *dst, size_t dst_len) { +int 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"; - const char *end = dst + dst_len - 1; - - for (; *src != '\0' && dst < end; src++, dst++) { - if (isalnum(*(const unsigned char *) src) || - strchr(dont_escape, * (const unsigned char *) src) != NULL) { - *dst = *src; - } else if (dst + 2 < end) { - dst[0] = '%'; - dst[1] = hex[(* (const unsigned char *) src) >> 4]; - dst[2] = hex[(* (const unsigned char *) src) & 0xf]; - dst += 2; + size_t i = 0, j = 0; + + for (i = j = 0; dst_len > 0 && i < s_len && j < 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 = '\0'; + dst[j] = '\0'; + return j; } #endif // !NO_DIRECTORY_LISTING || !MONGOOSE_NO_DAV @@ -3110,7 +3111,7 @@ static void print_dir_entry(const struct dir_entry *de) { } } strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", localtime(&de->st.st_mtime)); - mg_url_encode(de->file_name, href, sizeof(href)); + mg_url_encode(de->file_name, strlen(de->file_name), href, sizeof(href)); mg_printf_data(&de->conn->mg_conn, "<tr><td><a href=\"%s%s\">%s%s</a></td>" "<td> %s</td><td> %s</td></tr>\n", @@ -3231,7 +3232,7 @@ static void handle_propfind(struct connection *conn, const char *path, for (i = 0; i < num_entries; i++) { char buf[MAX_PATH_SIZE * 3]; struct dir_entry *de = &arr[i]; - mg_url_encode(de->file_name, buf, sizeof(buf) - 1); + mg_url_encode(de->file_name, strlen(de->file_name), buf, sizeof(buf)); print_props(conn, buf, &de->st); } } @@ -4306,7 +4307,7 @@ static void iter(struct ns_connection *nsconn, enum ns_event ev, void *param) { if (ev == NS_POLL) { struct mg_iterator *it = (struct mg_iterator *) param; struct connection *c = (struct connection *) nsconn->connection_data; - c->mg_conn.callback_param = it->param; + if (c != NULL) c->mg_conn.callback_param = it->param; it->cb(&c->mg_conn, MG_POLL); } } @@ -4572,9 +4573,26 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) { struct connection *conn = (struct connection *) nc->connection_data; struct mg_server *server = (struct mg_server *) nc->server; + // Send NS event to the handler. Note that call_user won't send an event + // if conn == NULL. Therefore, repeat this for NS_ACCEPT event as well. +#ifdef MONGOOSE_SEND_NS_EVENTS + { + struct connection *conn = (struct connection *) nc->connection_data; + if (conn != NULL) conn->mg_conn.callback_param = p; + call_user(conn, (enum mg_event) ev); + } +#endif + switch (ev) { case NS_ACCEPT: on_accept(nc, (union socket_address *) p); +#ifdef MONGOOSE_SEND_NS_EVENTS + { + struct connection *conn = (struct connection *) nc->connection_data; + if (conn != NULL) conn->mg_conn.callback_param = p; + call_user(conn, (enum mg_event) ev); + } +#endif break; case NS_CONNECT: @@ -4653,15 +4671,6 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) { default: break; } - -#ifdef MONGOOSE_SEND_NS_EVENTS - { - struct connection *conn = (struct connection *) nc->connection_data; - struct mg_connection *c = conn == NULL ? NULL : &conn->mg_conn; - if (c != NULL) c->callback_param = p; - if (server->event_handler) server->event_handler(c, (enum mg_event) ev); - } -#endif } void mg_wakeup_server(struct mg_server *server) { diff --git a/mongoose.h b/mongoose.h index ac7ceec28..0fd4251de 100644 --- a/mongoose.h +++ b/mongoose.h @@ -103,6 +103,8 @@ void mg_printf_data(struct mg_connection *, const char *format, ...); int mg_websocket_write(struct mg_connection *, int opcode, const char *data, size_t data_len); +int mg_websocket_printf(struct mg_connection* conn, int opcode, + const char *fmt, ...); // Deprecated in favor of mg_send_* interface int mg_write(struct mg_connection *, const void *buf, int len); @@ -122,7 +124,10 @@ int mg_parse_multipart(const char *buf, int buf_len, void *mg_start_thread(void *(*func)(void *), void *param); char *mg_md5(char buf[33], ...); int mg_authorize_digest(struct mg_connection *c, FILE *fp); +int mg_url_encode(const char *src, size_t s_len, char *dst, size_t dst_len); +int mg_url_decode(const char *src, int src_len, char *dst, int dst_len, int); +// Templates support struct mg_expansion { const char *keyword; void (*handler)(struct mg_connection *); -- GitLab