From 1640287897f4cf59b9b73f8a8864cdcba2b08885 Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Sat, 18 Jun 2022 04:23:56 +0100 Subject: [PATCH] Add mg_http_var --- docs/README.md | 23 ++++++++++++++++++++++- mongoose.c | 34 +++++++++++++++++----------------- mongoose.h | 1 + src/http.c | 34 +++++++++++++++++----------------- src/http.h | 1 + 5 files changed, 58 insertions(+), 35 deletions(-) diff --git a/docs/README.md b/docs/README.md index 5acbf8c6..c505dcd4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1148,6 +1148,25 @@ if (cookie != NULL) { } ``` +### mg\_http\_var() + +```c +struct mg_str mg_http_var(struct mg_str buf, struct mg_str name); +``` + +Fetch an undecoded HTTP variable. Parameters: +- `buf` - a url-encoded string: HTTP request body or query string +- `name` - a variable name to fetch + +Return value: variable's value. If not found, it it a NULL string. + + +```c +// We have received a request to /my/uri?a=b&c=d%20 +// The hm->query points to "a=b&c=d%20" +struct mg_str v = mg_http_var(hm->query, mg_str("c")); // v = "d%20" +``` + ### mg\_http\_get\_var() @@ -1155,7 +1174,7 @@ if (cookie != NULL) { int mg_http_get_var(const struct mg_str *var, const char *name, char *buf, int len); ``` -Decode HTTP variable +Fetch and decode an HTTP variable Parameters: - `var` - HTTP request body @@ -1170,6 +1189,8 @@ Usage example: ```c char buf[100] = ""; mg_http_get_var(&hm->body, "key1", buf, sizeof(buf)) { + ... +} ``` ### mg\_http\_creds() diff --git a/mongoose.c b/mongoose.c index a6a76684..9d472e83 100644 --- a/mongoose.c +++ b/mongoose.c @@ -1081,32 +1081,32 @@ void mg_http_bauth(struct mg_connection *c, const char *user, } } +struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) { + struct mg_str k, v, result = mg_str_n(NULL, 0); + while (mg_split(&buf, &k, &v, '&')) { + if (name.len == k.len && mg_ncasecmp(name.ptr, k.ptr, k.len) == 0) { + result = v; + break; + } + } + return result; +} + int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst, size_t dst_len) { - const char *p, *e, *s; - size_t name_len; int len; - if (dst == NULL || dst_len == 0) { len = -2; // Bad destination } else if (buf->ptr == NULL || name == NULL || buf->len == 0) { len = -1; // Bad source dst[0] = '\0'; } else { - name_len = strlen(name); - e = buf->ptr + buf->len; - len = -4; // Name does not exist - dst[0] = '\0'; - for (p = buf->ptr; p + name_len < e; p++) { - if ((p == buf->ptr || p[-1] == '&') && p[name_len] == '=' && - !mg_ncasecmp(name, p, name_len)) { - p += name_len + 1; - s = (const char *) memchr(p, '&', (size_t) (e - p)); - if (s == NULL) s = e; - len = mg_url_decode(p, (size_t) (s - p), dst, dst_len, 1); - if (len < 0) len = -3; // Failed to decode - break; - } + struct mg_str v = mg_http_var(*buf, mg_str(name)); + if (v.ptr == NULL) { + len = -4; // Name does not exist + } else { + len = mg_url_decode(v.ptr, v.len, dst, dst_len, 1); + if (len < 0) len = -3; // Failed to decode } } return len; diff --git a/mongoose.h b/mongoose.h index 90fdd09b..c84803f2 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1083,6 +1083,7 @@ void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm, void mg_http_reply(struct mg_connection *, int status_code, const char *headers, const char *body_fmt, ...); struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); +struct mg_str mg_http_var(struct mg_str buf, struct mg_str name); int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t); int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len); diff --git a/src/http.c b/src/http.c index 4284dc5c..0996884f 100644 --- a/src/http.c +++ b/src/http.c @@ -87,32 +87,32 @@ void mg_http_bauth(struct mg_connection *c, const char *user, } } +struct mg_str mg_http_var(struct mg_str buf, struct mg_str name) { + struct mg_str k, v, result = mg_str_n(NULL, 0); + while (mg_split(&buf, &k, &v, '&')) { + if (name.len == k.len && mg_ncasecmp(name.ptr, k.ptr, k.len) == 0) { + result = v; + break; + } + } + return result; +} + int mg_http_get_var(const struct mg_str *buf, const char *name, char *dst, size_t dst_len) { - const char *p, *e, *s; - size_t name_len; int len; - if (dst == NULL || dst_len == 0) { len = -2; // Bad destination } else if (buf->ptr == NULL || name == NULL || buf->len == 0) { len = -1; // Bad source dst[0] = '\0'; } else { - name_len = strlen(name); - e = buf->ptr + buf->len; - len = -4; // Name does not exist - dst[0] = '\0'; - for (p = buf->ptr; p + name_len < e; p++) { - if ((p == buf->ptr || p[-1] == '&') && p[name_len] == '=' && - !mg_ncasecmp(name, p, name_len)) { - p += name_len + 1; - s = (const char *) memchr(p, '&', (size_t) (e - p)); - if (s == NULL) s = e; - len = mg_url_decode(p, (size_t) (s - p), dst, dst_len, 1); - if (len < 0) len = -3; // Failed to decode - break; - } + struct mg_str v = mg_http_var(*buf, mg_str(name)); + if (v.ptr == NULL) { + len = -4; // Name does not exist + } else { + len = mg_url_decode(v.ptr, v.len, dst, dst_len, 1); + if (len < 0) len = -3; // Failed to decode } } return len; diff --git a/src/http.h b/src/http.h index 25e9a6cb..ab22c4e1 100644 --- a/src/http.h +++ b/src/http.h @@ -53,6 +53,7 @@ void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm, void mg_http_reply(struct mg_connection *, int status_code, const char *headers, const char *body_fmt, ...); struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name); +struct mg_str mg_http_var(struct mg_str buf, struct mg_str name); int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t); int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form); size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);