From 68c91a922286192c99925d2e8fa66aff28c754b8 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Fri, 20 May 2022 17:42:06 +0800 Subject: [PATCH 1/2] feat(http): add function url_decode and http_get_param_str --- plugins/restful/http.c | 31 +++++++++++++++++++++++++++++++ plugins/restful/http.h | 13 +++++++++++++ tests/http_test.cc | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/plugins/restful/http.c b/plugins/restful/http.c index 42d5cd5b..03a048e0 100644 --- a/plugins/restful/http.c +++ b/plugins/restful/http.c @@ -56,6 +56,26 @@ static int response(nng_aio *aio, char *content, enum nng_http_status status) return 0; } +ssize_t url_decode(const char *s, size_t len, char *buf, size_t size) +{ + size_t i = 0, j = 0; + int c = 0, n = 0; + while (i < len && j < size) { + c = s[i++]; + if ('+' == c) { + c = ' '; + } else if ('%' == c) { + if (i + 2 > len || !sscanf(s + i, "%2x%n", &c, &n) || 2 != n) { + return -1; + } + i += 2, n = 0; + } + buf[j++] = c; + } + buf[(j < size) ? j : --j] = '\0'; + return j; +} + const char *http_get_header(nng_aio *aio, char *name) { nng_http_req *req = nng_aio_get_input(aio, 0); @@ -153,6 +173,17 @@ const char *http_get_param(nng_aio *aio, const char *name, size_t *len) return val; } +ssize_t http_get_param_str(nng_aio *aio, const char *name, char *buf, + size_t size) +{ + size_t len = 0; + const char *s = http_get_param(aio, name, &len); + if (NULL == s) { + return -2; + } + return url_decode(s, len, buf, size); +} + int http_get_param_uintmax(nng_aio *aio, const char *name, uintmax_t *param) { size_t len = 0; diff --git a/plugins/restful/http.h b/plugins/restful/http.h index 90b3229d..a158f432 100644 --- a/plugins/restful/http.h +++ b/plugins/restful/http.h @@ -29,6 +29,12 @@ extern "C" { #endif +// Decode url encoded string. +// Return -1 if decode fails, otherwise return the number of bytes written to +// `buf` excluding the terminating NULL byte. A return value of `size` indicates +// buffer overflow. +ssize_t url_decode(const char *s, size_t len, char *buf, size_t size); + int http_get_body(nng_aio *aio, void **data, size_t *data_size); // Find query parameter value of the given name. @@ -47,6 +53,13 @@ int http_get_body(nng_aio *aio, void **data, size_t *data_size); // touch len. const char *http_get_param(nng_aio *aio, const char *name, size_t *len); +// Get query parameter as url decoded string. +// Return -2 if param does not exist, -1 if url decode fail, otherwise return +// the number of bytes written to `buf` excluding the terminating NULL byte. A +// return value of `size` indicates buffer overflow. +ssize_t http_get_param_str(nng_aio *aio, const char *name, char *buf, + size_t size); + // Returns 0 on success. // On failure returns // NEU_ERR_ENOENT if no query parameter named `name`. diff --git a/tests/http_test.cc b/tests/http_test.cc index 7394c902..4e0937a7 100644 --- a/tests/http_test.cc +++ b/tests/http_test.cc @@ -69,6 +69,43 @@ TEST(HTTPTest, http_get_param) nng_url_free(url); } +TEST(HTTPTest, http_get_param_str) +{ + nng_aio * aio = NULL; + nng_http_req *req = NULL; + nng_url * url = NULL; + ssize_t ret = 0; + + char buf[256] = { 0 }; + nng_aio_alloc(&aio, NULL, NULL); + nng_url_parse(&url, "http://127.0.0.1"); + nng_http_req_alloc(&req, url); + nng_aio_set_input(aio, 0, req); + + nng_http_req_set_uri(req, "/?node_id"); + ret = http_get_param_str(aio, "group", buf, sizeof(buf)); + EXPECT_EQ(ret, -2); + + nng_http_req_set_uri(req, "/?group"); + ret = http_get_param_str(aio, "group", buf, sizeof(buf)); + EXPECT_EQ(ret, 0); + EXPECT_EQ(0, strcmp("", buf)); + + nng_http_req_set_uri(req, "/?group=%EZ%BB%84"); + ret = http_get_param_str(aio, "group", buf, 3); + EXPECT_EQ(ret, -1); + EXPECT_EQ(0, strcmp("", buf)); + + nng_http_req_set_uri(req, "/?group=%E7%BB%84"); + ret = http_get_param_str(aio, "group", buf, 4); + EXPECT_EQ(ret, 3); + EXPECT_EQ(0, strcmp("组", buf)); + + nng_aio_free(aio); + nng_http_req_free(req); + nng_url_free(url); +} + TEST(HTTPTest, http_get_param_node_id) { nng_aio * aio = NULL; From c2a8c4f4f2d82b0ed3aad8703f4ba1f222dab677 Mon Sep 17 00:00:00 2001 From: eeff <33566201+eeff@users.noreply.github.com> Date: Fri, 20 May 2022 17:44:24 +0800 Subject: [PATCH 2/2] fix(restful): handle_get_tags url decode group name query parameter --- plugins/restful/datatag_handle.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/plugins/restful/datatag_handle.c b/plugins/restful/datatag_handle.c index c4be80a0..8612959c 100644 --- a/plugins/restful/datatag_handle.c +++ b/plugins/restful/datatag_handle.c @@ -257,9 +257,15 @@ void handle_get_tags(nng_aio *aio) return; } - size_t s_grp_name_len = 0; - const char *s_grp_name = - http_get_param(aio, "group_config_name", &s_grp_name_len); + char s_grp_name[256] = { 0 }; // should be large enough for the time being + ssize_t s_grp_name_len = http_get_param_str(aio, "group_config_name", + s_grp_name, sizeof(s_grp_name)); + if (-1 == s_grp_name_len || sizeof(s_grp_name) == s_grp_name_len) { + NEU_JSON_RESPONSE_ERROR(NEU_ERR_PARAM_IS_WRONG, { + http_response(aio, NEU_ERR_PARAM_IS_WRONG, result_error); + }) + return; + } neu_datatag_table_t *table = neu_system_get_datatags_table(plugin, node_id); if (table == NULL) { @@ -279,9 +285,9 @@ void handle_get_tags(nng_aio *aio) *(neu_taggrp_config_t **) iterator_get(&iter); const char *group_name = neu_taggrp_cfg_get_name(config); vector_t * ids = neu_taggrp_cfg_get_datatag_ids(config); - if (s_grp_name != NULL && - (strlen(group_name) != s_grp_name_len || - strncmp(group_name, s_grp_name, s_grp_name_len) != 0)) { + log_info("cai grp:%s s_grp_len:%zd s_grp:%.*s, ", group_name, + s_grp_name_len, s_grp_name); + if (-2 != s_grp_name_len && strcmp(group_name, s_grp_name) != 0) { continue; } @@ -297,9 +303,7 @@ void handle_get_tags(nng_aio *aio) *(neu_taggrp_config_t **) iterator_get(&iter); const char *group_name = neu_taggrp_cfg_get_name(config); - if (s_grp_name != NULL && - (strlen(group_name) != s_grp_name_len || - strncmp(group_name, s_grp_name, strlen(s_grp_name)) != 0)) { + if (-2 != s_grp_name_len && strcmp(group_name, s_grp_name) != 0) { continue; }