Commit 1bb98e5e authored by Sergey Lyubka's avatar Sergey Lyubka

Exported mg_websocket_printf(), mg_url_encode(). Added unit test for mg_url_encode()

parent a7774d0f
...@@ -271,6 +271,17 @@ static const char *test_url_decode(void) { ...@@ -271,6 +271,17 @@ static const char *test_url_decode(void) {
return NULL; 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) { static const char *test_to64(void) {
ASSERT(to64("0") == 0); ASSERT(to64("0") == 0);
ASSERT(to64("") == 0); ASSERT(to64("") == 0);
...@@ -498,6 +509,7 @@ static const char *run_all_tests(void) { ...@@ -498,6 +509,7 @@ static const char *run_all_tests(void) {
RUN_TEST(test_parse_http_message); RUN_TEST(test_parse_http_message);
RUN_TEST(test_to64); RUN_TEST(test_to64);
RUN_TEST(test_url_decode); RUN_TEST(test_url_decode);
RUN_TEST(test_url_encode);
RUN_TEST(test_base64_encode); RUN_TEST(test_base64_encode);
RUN_TEST(test_mg_parse_header); RUN_TEST(test_mg_parse_header);
RUN_TEST(test_get_var); RUN_TEST(test_get_var);
......
...@@ -3065,24 +3065,25 @@ static int scan_directory(struct connection *conn, const char *dir, ...@@ -3065,24 +3065,25 @@ static int scan_directory(struct connection *conn, const char *dir,
return arr_ind; 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 *dont_escape = "._-$,;~()";
static const char *hex = "0123456789abcdef"; static const char *hex = "0123456789abcdef";
const char *end = dst + dst_len - 1; size_t i = 0, j = 0;
for (; *src != '\0' && dst < end; src++, dst++) { for (i = j = 0; dst_len > 0 && i < s_len && j < dst_len - 1; i++, j++) {
if (isalnum(*(const unsigned char *) src) || if (isalnum(* (const unsigned char *) (src + i)) ||
strchr(dont_escape, * (const unsigned char *) src) != NULL) { strchr(dont_escape, * (const unsigned char *) (src + i)) != NULL) {
*dst = *src; dst[j] = src[i];
} else if (dst + 2 < end) { } else if (j + 3 < dst_len) {
dst[0] = '%'; dst[j] = '%';
dst[1] = hex[(* (const unsigned char *) src) >> 4]; dst[j + 1] = hex[(* (const unsigned char *) (src + i)) >> 4];
dst[2] = hex[(* (const unsigned char *) src) & 0xf]; dst[j + 2] = hex[(* (const unsigned char *) (src + i)) & 0xf];
dst += 2; j += 2;
} }
} }
*dst = '\0'; dst[j] = '\0';
return j;
} }
#endif // !NO_DIRECTORY_LISTING || !MONGOOSE_NO_DAV #endif // !NO_DIRECTORY_LISTING || !MONGOOSE_NO_DAV
...@@ -3110,7 +3111,7 @@ static void print_dir_entry(const struct dir_entry *de) { ...@@ -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)); 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, mg_printf_data(&de->conn->mg_conn,
"<tr><td><a href=\"%s%s\">%s%s</a></td>" "<tr><td><a href=\"%s%s\">%s%s</a></td>"
"<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n", "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
...@@ -3231,7 +3232,7 @@ static void handle_propfind(struct connection *conn, const char *path, ...@@ -3231,7 +3232,7 @@ static void handle_propfind(struct connection *conn, const char *path,
for (i = 0; i < num_entries; i++) { for (i = 0; i < num_entries; i++) {
char buf[MAX_PATH_SIZE * 3]; char buf[MAX_PATH_SIZE * 3];
struct dir_entry *de = &arr[i]; 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); print_props(conn, buf, &de->st);
} }
} }
...@@ -4306,7 +4307,7 @@ static void iter(struct ns_connection *nsconn, enum ns_event ev, void *param) { ...@@ -4306,7 +4307,7 @@ static void iter(struct ns_connection *nsconn, enum ns_event ev, void *param) {
if (ev == NS_POLL) { if (ev == NS_POLL) {
struct mg_iterator *it = (struct mg_iterator *) param; struct mg_iterator *it = (struct mg_iterator *) param;
struct connection *c = (struct connection *) nsconn->connection_data; 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); 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) { ...@@ -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 connection *conn = (struct connection *) nc->connection_data;
struct mg_server *server = (struct mg_server *) nc->server; 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) { switch (ev) {
case NS_ACCEPT: case NS_ACCEPT:
on_accept(nc, (union socket_address *) p); 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; break;
case NS_CONNECT: case NS_CONNECT:
...@@ -4653,15 +4671,6 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) { ...@@ -4653,15 +4671,6 @@ static void mg_ev_handler(struct ns_connection *nc, enum ns_event ev, void *p) {
default: default:
break; 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) { void mg_wakeup_server(struct mg_server *server) {
......
...@@ -103,6 +103,8 @@ void mg_printf_data(struct mg_connection *, const char *format, ...); ...@@ -103,6 +103,8 @@ void mg_printf_data(struct mg_connection *, const char *format, ...);
int mg_websocket_write(struct mg_connection *, int opcode, int mg_websocket_write(struct mg_connection *, int opcode,
const char *data, size_t data_len); 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 // Deprecated in favor of mg_send_* interface
int mg_write(struct mg_connection *, const void *buf, int len); 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, ...@@ -122,7 +124,10 @@ int mg_parse_multipart(const char *buf, int buf_len,
void *mg_start_thread(void *(*func)(void *), void *param); void *mg_start_thread(void *(*func)(void *), void *param);
char *mg_md5(char buf[33], ...); char *mg_md5(char buf[33], ...);
int mg_authorize_digest(struct mg_connection *c, FILE *fp); 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 { struct mg_expansion {
const char *keyword; const char *keyword;
void (*handler)(struct mg_connection *); void (*handler)(struct mg_connection *);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment