From 0117b90aa6d6eda61fba2295be98b12a19d85722 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 26 Jul 2018 11:57:44 +0000 Subject: [PATCH 1/8] Update: Added a (still unused) next member to the http_var_t structure --- httpp/httpp.c | 31 +++++++++++++++++++------------ httpp/httpp.h | 6 ++++-- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/httpp/httpp.c b/httpp/httpp.c index 78dd1cf..663224e 100644 --- a/httpp/httpp.c +++ b/httpp/httpp.c @@ -491,8 +491,10 @@ void httpp_deletevar(http_parser_t *parser, const char *name) if (parser == NULL || name == NULL) return; + memset(&var, 0, sizeof(var)); + var.name = (char*)name; - var.value = NULL; + avl_delete(parser->vars, (void *)&var, _free_vars); } @@ -503,7 +505,7 @@ void httpp_setvar(http_parser_t *parser, const char *name, const char *value) if (name == NULL || value == NULL) return; - var = (http_var_t *)malloc(sizeof(http_var_t)); + var = (http_var_t *)calloc(1, sizeof(http_var_t)); if (var == NULL) return; var->name = strdup(name); @@ -527,8 +529,8 @@ const char *httpp_getvar(http_parser_t *parser, const char *name) return NULL; fp = &found; + memset(&var, 0, sizeof(var)); var.name = (char*)name; - var.value = NULL; if (avl_get_by_key(parser->vars, &var, fp) == 0) return found->value; @@ -543,7 +545,7 @@ static void _httpp_set_param_nocopy(avl_tree *tree, char *name, char *value) if (name == NULL || value == NULL) return; - var = (http_var_t *)malloc(sizeof(http_var_t)); + var = (http_var_t *)calloc(1, sizeof(http_var_t)); if (var == NULL) return; var->name = name; @@ -572,8 +574,8 @@ static const char *_httpp_get_param(avl_tree *tree, const char *name) void *fp; fp = &found; + memset(&var, 0, sizeof(var)); var.name = (char *)name; - var.value = NULL; if (avl_get_by_key(tree, (void *)&var, fp) == 0) return found->value; @@ -650,15 +652,20 @@ static int _compare_vars(void *compare_arg, void *a, void *b) static int _free_vars(void *key) { - http_var_t *var; + http_var_t *var, *next; - var = (http_var_t *)key; + next = (http_var_t *)key; - if (var->name) - free(var->name); - if (var->value) - free(var->value); - free(var); + while (next) { + var = next; + next = var->next; + + if (var->name) + free(var->name); + if (var->value) + free(var->value); + free(var); + } return 1; } diff --git a/httpp/httpp.h b/httpp/httpp.h index 15a9a50..e3f1e12 100644 --- a/httpp/httpp.h +++ b/httpp/httpp.h @@ -61,10 +61,12 @@ typedef enum httpp_request_type_tag { httpp_req_unknown } httpp_request_type_e; -typedef struct http_var_tag { +typedef struct http_var_tag http_var_t; +struct http_var_tag { char *name; char *value; -} http_var_t; + http_var_t *next; +}; typedef struct http_varlist_tag { http_var_t var; From 53c13dd00e3db5f5b6f948b76dd5c8de34b49c11 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 26 Jul 2018 12:55:10 +0000 Subject: [PATCH 2/8] Update: Replaced next member with an array of values --- httpp/httpp.c | 106 ++++++++++++++++++++++++++++++++++++-------------- httpp/httpp.h | 4 +- 2 files changed, 78 insertions(+), 32 deletions(-) diff --git a/httpp/httpp.c b/httpp/httpp.c index 663224e..fa09db0 100644 --- a/httpp/httpp.c +++ b/httpp/httpp.c @@ -55,8 +55,9 @@ static int _free_vars(void *key); /* For avl tree manipulation */ static void parse_query(avl_tree *tree, const char *query, size_t len); static const char *_httpp_get_param(avl_tree *tree, const char *name); -static void _httpp_set_param_nocopy(avl_tree *tree, char *name, char *value); +static void _httpp_set_param_nocopy(avl_tree *tree, char *name, char *value, int replace); static void _httpp_set_param(avl_tree *tree, const char *name, const char *value); +static http_var_t *_httpp_get_param_var(avl_tree *tree, const char *name); http_parser_t *httpp_create_parser(void) { @@ -76,7 +77,12 @@ void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults) /* now insert the default variables */ list = defaults; while (list != NULL) { - httpp_setvar(parser, list->var.name, list->var.value); + size_t i; + + for (i = 0; i < list->var.values; i++) { + httpp_setvar(parser, list->var.name, list->var.value[i]); + } + list = list->next; } } @@ -310,7 +316,7 @@ static void parse_query_element(avl_tree *tree, const char *start, const char *m value = url_unescape(mid + 1, valuelen); - _httpp_set_param_nocopy(tree, key, value); + _httpp_set_param_nocopy(tree, key, value, 0); } static void parse_query(avl_tree *tree, const char *query, size_t len) @@ -508,8 +514,15 @@ void httpp_setvar(http_parser_t *parser, const char *name, const char *value) var = (http_var_t *)calloc(1, sizeof(http_var_t)); if (var == NULL) return; + var->value = calloc(1, sizeof(*var->value)); + if (!var->value) { + free(var); + return; + } + var->name = strdup(name); - var->value = strdup(value); + var->values = 1; + var->value[0] = strdup(value); if (httpp_getvar(parser, name) == NULL) { avl_insert(parser->vars, (void *)var); @@ -532,29 +545,54 @@ const char *httpp_getvar(http_parser_t *parser, const char *name) memset(&var, 0, sizeof(var)); var.name = (char*)name; - if (avl_get_by_key(parser->vars, &var, fp) == 0) - return found->value; - else + if (avl_get_by_key(parser->vars, &var, fp) == 0) { + if (!found->values) + return NULL; + return found->value[0]; + } else { return NULL; + } } -static void _httpp_set_param_nocopy(avl_tree *tree, char *name, char *value) +static void _httpp_set_param_nocopy(avl_tree *tree, char *name, char *value, int replace) { - http_var_t *var; + http_var_t *var, *found; + char **n; if (name == NULL || value == NULL) return; - var = (http_var_t *)calloc(1, sizeof(http_var_t)); - if (var == NULL) return; + found = _httpp_get_param_var(tree, name); - var->name = name; - var->value = value; + if (replace || !found) { + var = (http_var_t *)calloc(1, sizeof(http_var_t)); + if (var == NULL) { + free(name); + free(value); + return; + } - if (_httpp_get_param(tree, name) == NULL) { - avl_insert(tree, (void *)var); + var->name = name; } else { - avl_delete(tree, (void *)var, _free_vars); + free(name); + var = found; + } + + n = realloc(var->value, sizeof(*n)*(var->values + 1)); + if (!n) { + if (replace || !found) { + free(name); + free(var); + } + free(value); + return; + } + + var->value = n; + var->value[var->values++] = value; + + if (replace && found) { + avl_delete(tree, (void *)found, _free_vars); avl_insert(tree, (void *)var); } } @@ -564,10 +602,10 @@ static void _httpp_set_param(avl_tree *tree, const char *name, const char *value if (name == NULL || value == NULL) return; - _httpp_set_param_nocopy(tree, strdup(name), url_unescape(value, strlen(value))); + _httpp_set_param_nocopy(tree, strdup(name), url_unescape(value, strlen(value)), 1); } -static const char *_httpp_get_param(avl_tree *tree, const char *name) +static http_var_t *_httpp_get_param_var(avl_tree *tree, const char *name) { http_var_t var; http_var_t *found; @@ -578,10 +616,22 @@ static const char *_httpp_get_param(avl_tree *tree, const char *name) var.name = (char *)name; if (avl_get_by_key(tree, (void *)&var, fp) == 0) - return found->value; + return found; else return NULL; } +static const char *_httpp_get_param(avl_tree *tree, const char *name) +{ + http_var_t *res = _httpp_get_param_var(tree, name); + + if (!res) + return NULL; + + if (!res->values) + return NULL; + + return res->value[0]; +} void httpp_set_query_param(http_parser_t *parser, const char *name, const char *value) { @@ -652,20 +702,16 @@ static int _compare_vars(void *compare_arg, void *a, void *b) static int _free_vars(void *key) { - http_var_t *var, *next; + http_var_t *var = (http_var_t *)key; + size_t i; - next = (http_var_t *)key; + free(var->name); - while (next) { - var = next; - next = var->next; - - if (var->name) - free(var->name); - if (var->value) - free(var->value); - free(var); + for (i = 0; i < var->values; i++) { + free(var->value[i]); } + free(var->value); + free(var); return 1; } diff --git a/httpp/httpp.h b/httpp/httpp.h index e3f1e12..f8073a9 100644 --- a/httpp/httpp.h +++ b/httpp/httpp.h @@ -64,8 +64,8 @@ typedef enum httpp_request_type_tag { typedef struct http_var_tag http_var_t; struct http_var_tag { char *name; - char *value; - http_var_t *next; + size_t values; + char **value; }; typedef struct http_varlist_tag { From 7d2b9fa3fd4be2c332c2e4573c187eaeccf83c4d Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 26 Jul 2018 12:59:23 +0000 Subject: [PATCH 3/8] Feature: Added httpp_get_param_var() so multi-value access is possible --- httpp/httpp.c | 10 ++++++++++ httpp/httpp.h | 1 + 2 files changed, 11 insertions(+) diff --git a/httpp/httpp.c b/httpp/httpp.c index fa09db0..0707973 100644 --- a/httpp/httpp.c +++ b/httpp/httpp.c @@ -653,6 +653,16 @@ const char *httpp_get_post_param(http_parser_t *parser, const char *name) return _httpp_get_param(parser->postvars, name); } +const http_var_t *httpp_get_param_var(http_parser_t *parser, const char *name) +{ + http_var_t *ret = _httpp_get_param_var(parser->postvars, name); + + if (ret) + return ret; + + return _httpp_get_param_var(parser->queryvars, name); +} + const char *httpp_get_param(http_parser_t *parser, const char *name) { const char *ret = _httpp_get_param(parser->postvars, name); diff --git a/httpp/httpp.h b/httpp/httpp.h index f8073a9..b5cd327 100644 --- a/httpp/httpp.h +++ b/httpp/httpp.h @@ -113,6 +113,7 @@ const char *httpp_get_query_param(http_parser_t *parser, const char *name); void httpp_set_post_param(http_parser_t *parser, const char *name, const char *value); const char *httpp_get_post_param(http_parser_t *parser, const char *name); const char *httpp_get_param(http_parser_t *parser, const char *name); +const http_var_t *httpp_get_param_var(http_parser_t *parser, const char *name); void httpp_destroy(http_parser_t *parser); void httpp_clear(http_parser_t *parser); From 1f5741078873bd46cf818bfc3c2409193a18f019 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 26 Jul 2018 13:08:25 +0000 Subject: [PATCH 4/8] Fix: Actually insert nodes into the tree if they are new --- httpp/httpp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/httpp/httpp.c b/httpp/httpp.c index 0707973..40d4206 100644 --- a/httpp/httpp.c +++ b/httpp/httpp.c @@ -594,6 +594,8 @@ static void _httpp_set_param_nocopy(avl_tree *tree, char *name, char *value, int if (replace && found) { avl_delete(tree, (void *)found, _free_vars); avl_insert(tree, (void *)var); + } else if (!found) { + avl_insert(tree, (void *)var); } } From aeddcad5df5ba7bfac558be2794aa3be88d4abe4 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 2 Aug 2018 09:00:32 +0000 Subject: [PATCH 5/8] Feature: Added httpp_request_info() --- httpp/httpp.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ httpp/httpp.h | 11 ++++++++++ 2 files changed, 68 insertions(+) diff --git a/httpp/httpp.c b/httpp/httpp.c index 40d4206..470ceeb 100644 --- a/httpp/httpp.c +++ b/httpp/httpp.c @@ -59,6 +59,63 @@ static void _httpp_set_param_nocopy(avl_tree *tree, char *name, char *value, int static void _httpp_set_param(avl_tree *tree, const char *name, const char *value); static http_var_t *_httpp_get_param_var(avl_tree *tree, const char *name); +httpp_request_info_t httpp_request_info(httpp_request_type_e req) +{ +#if 0 +#define HTTPP_REQUEST_IS_SAFE ((httpp_request_info_t)0x0001U) +#define HTTPP_REQUEST_IS_IDEMPOTENT ((httpp_request_info_t)0x0002U) +#define HTTPP_REQUEST_IS_CACHEABLE ((httpp_request_info_t)0x0004U) +#define HTTPP_REQUEST_HAS_RESPONSE_BODY ((httpp_request_info_t)0x0010U) +#define HTTPP_REQUEST_HAS_REQUEST_BODY ((httpp_request_info_t)0x0100U) +#define HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY ((httpp_request_info_t)0x0200U) +#endif + switch (req) { + /* offical methods */ + case httpp_req_get: + return HTTPP_REQUEST_IS_SAFE|HTTPP_REQUEST_IS_IDEMPOTENT|HTTPP_REQUEST_IS_CACHEABLE|HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY; + break; + case httpp_req_post: + return HTTPP_REQUEST_IS_CACHEABLE|HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_REQUEST_BODY; + break; + case httpp_req_put: + return HTTPP_REQUEST_IS_IDEMPOTENT|HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_REQUEST_BODY; + break; + case httpp_req_head: + return HTTPP_REQUEST_IS_SAFE|HTTPP_REQUEST_IS_IDEMPOTENT|HTTPP_REQUEST_IS_CACHEABLE; + break; + case httpp_req_options: + return HTTPP_REQUEST_IS_SAFE|HTTPP_REQUEST_IS_IDEMPOTENT|HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY; + break; + case httpp_req_delete: + return HTTPP_REQUEST_IS_IDEMPOTENT|HTTPP_REQUEST_HAS_RESPONSE_BODY; + break; + case httpp_req_trace: + return HTTPP_REQUEST_IS_SAFE|HTTPP_REQUEST_IS_IDEMPOTENT|HTTPP_REQUEST_HAS_RESPONSE_BODY; + break; + case httpp_req_connect: + return HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_REQUEST_BODY; + break; + + /* Icecast specific methods */ + case httpp_req_source: + return HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_REQUEST_BODY; + break; + case httpp_req_play: + return HTTPP_REQUEST_IS_SAFE|HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY; + break; + case httpp_req_stats: + return HTTPP_REQUEST_IS_SAFE|HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY; + break; + + /* Virtual and other methods */ + case httpp_req_none: + case httpp_req_unknown: + default: + return HTTPP_REQUEST_HAS_RESPONSE_BODY|HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY; + break; + } +} + http_parser_t *httpp_create_parser(void) { return (http_parser_t *)malloc(sizeof(http_parser_t)); diff --git a/httpp/httpp.h b/httpp/httpp.h index b5cd327..89ae85a 100644 --- a/httpp/httpp.h +++ b/httpp/httpp.h @@ -61,6 +61,14 @@ typedef enum httpp_request_type_tag { httpp_req_unknown } httpp_request_type_e; +typedef unsigned int httpp_request_info_t; +#define HTTPP_REQUEST_IS_SAFE ((httpp_request_info_t)0x0001U) +#define HTTPP_REQUEST_IS_IDEMPOTENT ((httpp_request_info_t)0x0002U) +#define HTTPP_REQUEST_IS_CACHEABLE ((httpp_request_info_t)0x0004U) +#define HTTPP_REQUEST_HAS_RESPONSE_BODY ((httpp_request_info_t)0x0010U) +#define HTTPP_REQUEST_HAS_REQUEST_BODY ((httpp_request_info_t)0x0100U) +#define HTTPP_REQUEST_HAS_OPTIONAL_REQUEST_BODY ((httpp_request_info_t)0x0200U) + typedef struct http_var_tag http_var_t; struct http_var_tag { char *name; @@ -82,6 +90,7 @@ typedef struct http_parser_tag { } http_parser_t; #ifdef _mangle +# define httpp_request_info _mangle(httpp_request_info) # define httpp_create_parser _mangle(httpp_create_parser) # define httpp_initialize _mangle(httpp_initialize) # define httpp_parse _mangle(httpp_parse) @@ -99,6 +108,8 @@ typedef struct http_parser_tag { # define httpp_clear _mangle(httpp_clear) #endif +httpp_request_info_t httpp_request_info(httpp_request_type_e req); + http_parser_t *httpp_create_parser(void); void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults); int httpp_parse(http_parser_t *parser, const char *http_data, unsigned long len); From 03659eb096faf00454cdacfd6888e376c301bfb2 Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 9 Aug 2018 09:25:26 +0000 Subject: [PATCH 6/8] Feature: Added reference counting to httpp parser object --- httpp/httpp.c | 38 ++++++++++++++++++++++++++++++-------- httpp/httpp.h | 6 ++++-- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/httpp/httpp.c b/httpp/httpp.c index 470ceeb..4c51b7a 100644 --- a/httpp/httpp.c +++ b/httpp/httpp.c @@ -118,19 +118,22 @@ httpp_request_info_t httpp_request_info(httpp_request_type_e req) http_parser_t *httpp_create_parser(void) { - return (http_parser_t *)malloc(sizeof(http_parser_t)); -} - -void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults) -{ - http_varlist_t *list; + http_parser_t *parser = calloc(1, sizeof(http_parser_t)); + parser->refc = 1; parser->req_type = httpp_req_none; parser->uri = NULL; parser->vars = avl_tree_new(_compare_vars, NULL); parser->queryvars = avl_tree_new(_compare_vars, NULL); parser->postvars = avl_tree_new(_compare_vars, NULL); + return parser; +} + +void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults) +{ + http_varlist_t *list; + /* now insert the default variables */ list = defaults; while (list != NULL) { @@ -732,7 +735,7 @@ const char *httpp_get_param(http_parser_t *parser, const char *name) return _httpp_get_param(parser->queryvars, name); } -void httpp_clear(http_parser_t *parser) +static void httpp_clear(http_parser_t *parser) { parser->req_type = httpp_req_none; if (parser->uri) @@ -744,10 +747,29 @@ void httpp_clear(http_parser_t *parser) parser->vars = NULL; } -void httpp_destroy(http_parser_t *parser) +int httpp_addref(http_parser_t *parser) { + if (!parser) + return -1; + + parser->refc++; + + return 0; +} + +int httpp_release(http_parser_t *parser) +{ + if (!parser) + return -1; + + parser->refc--; + if (parser->refc) + return 0; + httpp_clear(parser); free(parser); + + return 0; } static char *_lowercase(char *str) diff --git a/httpp/httpp.h b/httpp/httpp.h index 89ae85a..8302cd5 100644 --- a/httpp/httpp.h +++ b/httpp/httpp.h @@ -82,6 +82,7 @@ typedef struct http_varlist_tag { } http_varlist_t; typedef struct http_parser_tag { + size_t refc; httpp_request_type_e req_type; char *uri; avl_tree *vars; @@ -125,8 +126,9 @@ void httpp_set_post_param(http_parser_t *parser, const char *name, const char *v const char *httpp_get_post_param(http_parser_t *parser, const char *name); const char *httpp_get_param(http_parser_t *parser, const char *name); const http_var_t *httpp_get_param_var(http_parser_t *parser, const char *name); -void httpp_destroy(http_parser_t *parser); -void httpp_clear(http_parser_t *parser); +int httpp_addref(http_parser_t *parser); +int httpp_release(http_parser_t *parser); +#define httpp_destroy(x) httpp_release((x)) /* util functions */ httpp_request_type_e httpp_str_to_method(const char * method); From c1d41f38b0db0070d171ad09e98a0339883720cf Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 9 Aug 2018 11:13:10 +0000 Subject: [PATCH 7/8] Cleanup: Fixed 9 year old typo. --- httpp/httpp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpp/httpp.h b/httpp/httpp.h index 8302cd5..0d4d137 100644 --- a/httpp/httpp.h +++ b/httpp/httpp.h @@ -33,7 +33,7 @@ #define HTTPP_VAR_VERSION "__version" #define HTTPP_VAR_URI "__uri" #define HTTPP_VAR_RAWURI "__rawuri" -#define HTTPP_VAR_QUERYARGS " __queryargs" +#define HTTPP_VAR_QUERYARGS "__queryargs" #define HTTPP_VAR_REQ_TYPE "__req_type" #define HTTPP_VAR_ERROR_MESSAGE "__errormessage" #define HTTPP_VAR_ERROR_CODE "__errorcode" From 6492a456a1634c4b5d3087bfe74672af926de7ba Mon Sep 17 00:00:00 2001 From: Philipp Schafft Date: Thu, 9 Aug 2018 11:17:38 +0000 Subject: [PATCH 8/8] Feature: Allow enumeration of parser content --- httpp/httpp.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++ httpp/httpp.h | 10 +++++ 2 files changed, 124 insertions(+) diff --git a/httpp/httpp.c b/httpp/httpp.c index 4c51b7a..3c14448 100644 --- a/httpp/httpp.c +++ b/httpp/httpp.c @@ -725,6 +725,120 @@ const http_var_t *httpp_get_param_var(http_parser_t *parser, const char *name) return _httpp_get_param_var(parser->queryvars, name); } +const http_var_t *httpp_get_any_var(http_parser_t *parser, httpp_ns_t ns, const char *name) +{ + avl_tree *tree = NULL; + + if (!parser || !name) + return NULL; + + switch (ns) { + case HTTPP_NS_VAR: + if (name[0] != '_' || name[1] != '_') + return NULL; + tree = parser->vars; + break; + case HTTPP_NS_HEADER: + if (name[0] == '_' && name[1] == '_') + return NULL; + tree = parser->vars; + break; + case HTTPP_NS_QUERY_STRING: + tree = parser->queryvars; + break; + case HTTPP_NS_POST_BODY: + tree = parser->postvars; + break; + } + + if (!tree) + return NULL; + + return _httpp_get_param_var(tree, name); +} + +char ** httpp_get_any_key(http_parser_t *parser, httpp_ns_t ns) +{ + avl_tree *tree = NULL; + avl_node *avlnode; + char **ret; + size_t len; + size_t pos = 0; + + if (!parser) + return NULL; + + switch (ns) { + case HTTPP_NS_VAR: + case HTTPP_NS_HEADER: + tree = parser->vars; + break; + case HTTPP_NS_QUERY_STRING: + tree = parser->queryvars; + break; + case HTTPP_NS_POST_BODY: + tree = parser->postvars; + break; + } + + if (!tree) + return NULL; + + ret = calloc(8, sizeof(*ret)); + if (!ret) + return NULL; + + len = 8; + + for (avlnode = avl_get_first(tree); avlnode; avlnode = avl_get_next(avlnode)) { + http_var_t *var = avlnode->key; + + if (ns == HTTPP_NS_VAR) { + if (var->name[0] != '_' || var->name[1] != '_') { + continue; + } + } else if (ns == HTTPP_NS_HEADER) { + if (var->name[0] == '_' && var->name[1] == '_') { + continue; + } + } + + if (pos == (len-1)) { + char **n = realloc(ret, sizeof(*ret)*(len + 8)); + if (!n) { + httpp_free_any_key(ret); + return NULL; + } + memset(n + len, 0, sizeof(*n)*8); + ret = n; + len += 8; + } + + ret[pos] = strdup(var->name); + if (!ret[pos]) { + httpp_free_any_key(ret); + return NULL; + } + + pos++; + } + + return ret; +} + +void httpp_free_any_key(char **keys) +{ + char **p; + + if (!keys) + return; + + for (p = keys; *p; p++) { + free(*p); + } + free(keys); +} + const char *httpp_get_param(http_parser_t *parser, const char *name) { const char *ret = _httpp_get_param(parser->postvars, name); diff --git a/httpp/httpp.h b/httpp/httpp.h index 0d4d137..824d296 100644 --- a/httpp/httpp.h +++ b/httpp/httpp.h @@ -39,6 +39,13 @@ #define HTTPP_VAR_ERROR_CODE "__errorcode" #define HTTPP_VAR_ICYPASSWORD "__icy_password" +typedef enum { + HTTPP_NS_VAR, + HTTPP_NS_HEADER, + HTTPP_NS_QUERY_STRING, + HTTPP_NS_POST_BODY +} httpp_ns_t; + typedef enum httpp_request_type_tag { /* Initial and internally used state of the engine */ httpp_req_none = 0, @@ -126,6 +133,9 @@ void httpp_set_post_param(http_parser_t *parser, const char *name, const char *v const char *httpp_get_post_param(http_parser_t *parser, const char *name); const char *httpp_get_param(http_parser_t *parser, const char *name); const http_var_t *httpp_get_param_var(http_parser_t *parser, const char *name); +const http_var_t *httpp_get_any_var(http_parser_t *parser, httpp_ns_t ns, const char *name); +char ** httpp_get_any_key(http_parser_t *parser, httpp_ns_t ns); +void httpp_free_any_key(char **keys); int httpp_addref(http_parser_t *parser); int httpp_release(http_parser_t *parser); #define httpp_destroy(x) httpp_release((x))