mirror of
https://gitlab.xiph.org/xiph/icecast-common.git
synced 2024-12-04 14:46:31 -05:00
Feature: Added support to parse POST data
This commit is contained in:
parent
fca416b126
commit
937268e288
138
httpp/httpp.c
138
httpp/httpp.c
@ -52,6 +52,12 @@ static char *_lowercase(char *str);
|
|||||||
static int _compare_vars(void *compare_arg, void *a, void *b);
|
static int _compare_vars(void *compare_arg, void *a, void *b);
|
||||||
static int _free_vars(void *key);
|
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(avl_tree *tree, const char *name, const char *value);
|
||||||
|
|
||||||
http_parser_t *httpp_create_parser(void)
|
http_parser_t *httpp_create_parser(void)
|
||||||
{
|
{
|
||||||
return (http_parser_t *)malloc(sizeof(http_parser_t));
|
return (http_parser_t *)malloc(sizeof(http_parser_t));
|
||||||
@ -65,6 +71,7 @@ void httpp_initialize(http_parser_t *parser, http_varlist_t *defaults)
|
|||||||
parser->uri = NULL;
|
parser->uri = NULL;
|
||||||
parser->vars = avl_tree_new(_compare_vars, NULL);
|
parser->vars = avl_tree_new(_compare_vars, NULL);
|
||||||
parser->queryvars = avl_tree_new(_compare_vars, NULL);
|
parser->queryvars = avl_tree_new(_compare_vars, NULL);
|
||||||
|
parser->postvars = avl_tree_new(_compare_vars, NULL);
|
||||||
|
|
||||||
/* now insert the default variables */
|
/* now insert the default variables */
|
||||||
list = defaults;
|
list = defaults;
|
||||||
@ -203,6 +210,19 @@ int httpp_parse_response(http_parser_t *parser, const char *http_data, unsigned
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int httpp_parse_postdata(http_parser_t *parser, const char *body_data, size_t len)
|
||||||
|
{
|
||||||
|
const char *header = httpp_getvar(parser, "content-type");
|
||||||
|
|
||||||
|
if (strcasecmp(header, "application/x-www-form-urlencoded") != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_query(parser->postvars, body_data, len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int hex(char c)
|
static int hex(char c)
|
||||||
{
|
{
|
||||||
if(c >= '0' && c <= '9')
|
if(c >= '0' && c <= '9')
|
||||||
@ -215,11 +235,10 @@ static int hex(char c)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *url_escape(const char *src)
|
static char *url_unescape(const char *src, size_t len)
|
||||||
{
|
{
|
||||||
int len = strlen(src);
|
|
||||||
unsigned char *decoded;
|
unsigned char *decoded;
|
||||||
int i;
|
size_t i;
|
||||||
char *dst;
|
char *dst;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
|
|
||||||
@ -265,38 +284,58 @@ static char *url_escape(const char *src)
|
|||||||
return (char *)decoded;
|
return (char *)decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** TODO: This is almost certainly buggy in some cases */
|
static void parse_query_element(avl_tree *tree, const char *start, const char *mid, const char *end)
|
||||||
static void parse_query(http_parser_t *parser, char *query)
|
|
||||||
{
|
{
|
||||||
int len;
|
size_t keylen;
|
||||||
int i=0;
|
char *key;
|
||||||
char *key = query;
|
size_t valuelen;
|
||||||
char *val=NULL;
|
char *value;
|
||||||
|
|
||||||
if(!query || !*query)
|
if (start >= end)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
len = strlen(query);
|
if (!mid)
|
||||||
|
return;
|
||||||
|
|
||||||
while(i<len) {
|
keylen = mid - start;
|
||||||
switch(query[i]) {
|
valuelen = end - mid - 1;
|
||||||
case '&':
|
|
||||||
query[i] = 0;
|
/* REVIEW: We ignore keys with empty values. */
|
||||||
if(val && key)
|
if (!keylen || !valuelen)
|
||||||
httpp_set_query_param(parser, key, val);
|
return;
|
||||||
key = query+i+1;
|
|
||||||
|
key = malloc(keylen + 1);
|
||||||
|
memcpy(key, start, keylen);
|
||||||
|
key[keylen] = 0;
|
||||||
|
|
||||||
|
value = url_unescape(mid + 1, valuelen);
|
||||||
|
|
||||||
|
_httpp_set_param_nocopy(tree, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void parse_query(avl_tree *tree, const char *query, size_t len)
|
||||||
|
{
|
||||||
|
const char *start = query;
|
||||||
|
const char *mid = NULL;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!query || !*query)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
switch (query[i]) {
|
||||||
|
case '&':
|
||||||
|
parse_query_element(tree, start, mid, &(query[i]));
|
||||||
|
start = &(query[i + 1]);
|
||||||
|
mid = NULL;
|
||||||
break;
|
break;
|
||||||
case '=':
|
case '=':
|
||||||
query[i] = 0;
|
mid = &(query[i]);
|
||||||
val = query+i+1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(val && key) {
|
parse_query_element(tree, start, mid, &(query[i]));
|
||||||
httpp_set_query_param(parser, key, val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int httpp_parse(http_parser_t *parser, const char *http_data, unsigned long len)
|
int httpp_parse(http_parser_t *parser, const char *http_data, unsigned long len)
|
||||||
@ -361,7 +400,7 @@ int httpp_parse(http_parser_t *parser, const char *http_data, unsigned long len)
|
|||||||
httpp_setvar(parser, HTTPP_VAR_QUERYARGS, query);
|
httpp_setvar(parser, HTTPP_VAR_QUERYARGS, query);
|
||||||
*query = 0;
|
*query = 0;
|
||||||
query++;
|
query++;
|
||||||
parse_query(parser, query);
|
parse_query(parser->queryvars, query, strlen(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->uri = strdup(uri);
|
parser->uri = strdup(uri);
|
||||||
@ -492,7 +531,7 @@ const char *httpp_getvar(http_parser_t *parser, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void httpp_set_query_param(http_parser_t *parser, const char *name, const char *value)
|
static void _httpp_set_param_nocopy(avl_tree *tree, char *name, char *value)
|
||||||
{
|
{
|
||||||
http_var_t *var;
|
http_var_t *var;
|
||||||
|
|
||||||
@ -502,18 +541,26 @@ void httpp_set_query_param(http_parser_t *parser, const char *name, const char *
|
|||||||
var = (http_var_t *)malloc(sizeof(http_var_t));
|
var = (http_var_t *)malloc(sizeof(http_var_t));
|
||||||
if (var == NULL) return;
|
if (var == NULL) return;
|
||||||
|
|
||||||
var->name = strdup(name);
|
var->name = name;
|
||||||
var->value = url_escape(value);
|
var->value = value;
|
||||||
|
|
||||||
if (httpp_get_query_param(parser, name) == NULL) {
|
if (_httpp_get_param(tree, name) == NULL) {
|
||||||
avl_insert(parser->queryvars, (void *)var);
|
avl_insert(tree, (void *)var);
|
||||||
} else {
|
} else {
|
||||||
avl_delete(parser->queryvars, (void *)var, _free_vars);
|
avl_delete(tree, (void *)var, _free_vars);
|
||||||
avl_insert(parser->queryvars, (void *)var);
|
avl_insert(tree, (void *)var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *httpp_get_query_param(http_parser_t *parser, const char *name)
|
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)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *_httpp_get_param(avl_tree *tree, const char *name)
|
||||||
{
|
{
|
||||||
http_var_t var;
|
http_var_t var;
|
||||||
http_var_t *found;
|
http_var_t *found;
|
||||||
@ -523,12 +570,32 @@ const char *httpp_get_query_param(http_parser_t *parser, const char *name)
|
|||||||
var.name = (char *)name;
|
var.name = (char *)name;
|
||||||
var.value = NULL;
|
var.value = NULL;
|
||||||
|
|
||||||
if (avl_get_by_key(parser->queryvars, (void *)&var, fp) == 0)
|
if (avl_get_by_key(tree, (void *)&var, fp) == 0)
|
||||||
return found->value;
|
return found->value;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void httpp_set_query_param(http_parser_t *parser, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
return _httpp_set_param(parser->queryvars, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *httpp_get_query_param(http_parser_t *parser, const char *name)
|
||||||
|
{
|
||||||
|
return _httpp_get_param(parser->queryvars, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void httpp_set_post_param(http_parser_t *parser, const char *name, const char *value)
|
||||||
|
{
|
||||||
|
return _httpp_set_param(parser->postvars, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *httpp_get_post_param(http_parser_t *parser, const char *name)
|
||||||
|
{
|
||||||
|
return _httpp_get_param(parser->postvars, name);
|
||||||
|
}
|
||||||
|
|
||||||
void httpp_clear(http_parser_t *parser)
|
void httpp_clear(http_parser_t *parser)
|
||||||
{
|
{
|
||||||
parser->req_type = httpp_req_none;
|
parser->req_type = httpp_req_none;
|
||||||
@ -537,6 +604,7 @@ void httpp_clear(http_parser_t *parser)
|
|||||||
parser->uri = NULL;
|
parser->uri = NULL;
|
||||||
avl_tree_free(parser->vars, _free_vars);
|
avl_tree_free(parser->vars, _free_vars);
|
||||||
avl_tree_free(parser->queryvars, _free_vars);
|
avl_tree_free(parser->queryvars, _free_vars);
|
||||||
|
avl_tree_free(parser->postvars, _free_vars);
|
||||||
parser->vars = NULL;
|
parser->vars = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ typedef struct http_parser_tag {
|
|||||||
char *uri;
|
char *uri;
|
||||||
avl_tree *vars;
|
avl_tree *vars;
|
||||||
avl_tree *queryvars;
|
avl_tree *queryvars;
|
||||||
|
avl_tree *postvars;
|
||||||
} http_parser_t;
|
} http_parser_t;
|
||||||
|
|
||||||
#ifdef _mangle
|
#ifdef _mangle
|
||||||
@ -97,11 +98,14 @@ 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);
|
int httpp_parse(http_parser_t *parser, const char *http_data, unsigned long len);
|
||||||
int httpp_parse_icy(http_parser_t *parser, const char *http_data, unsigned long len);
|
int httpp_parse_icy(http_parser_t *parser, const char *http_data, unsigned long len);
|
||||||
int httpp_parse_response(http_parser_t *parser, const char *http_data, unsigned long len, const char *uri);
|
int httpp_parse_response(http_parser_t *parser, const char *http_data, unsigned long len, const char *uri);
|
||||||
|
int httpp_parse_postdata(http_parser_t *parser, const char *body_data, size_t len);
|
||||||
void httpp_setvar(http_parser_t *parser, const char *name, const char *value);
|
void httpp_setvar(http_parser_t *parser, const char *name, const char *value);
|
||||||
void httpp_deletevar(http_parser_t *parser, const char *name);
|
void httpp_deletevar(http_parser_t *parser, const char *name);
|
||||||
const char *httpp_getvar(http_parser_t *parser, const char *name);
|
const char *httpp_getvar(http_parser_t *parser, const char *name);
|
||||||
void httpp_set_query_param(http_parser_t *parser, const char *name, const char *value);
|
void httpp_set_query_param(http_parser_t *parser, const char *name, const char *value);
|
||||||
const char *httpp_get_query_param(http_parser_t *parser, const char *name);
|
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);
|
||||||
void httpp_destroy(http_parser_t *parser);
|
void httpp_destroy(http_parser_t *parser);
|
||||||
void httpp_clear(http_parser_t *parser);
|
void httpp_clear(http_parser_t *parser);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user