#include <sys/queue.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>
#include <event2/event_struct.h>
#include "http.h"
#include "common.h"
int http_qarg_parse (struct evhttp_request *request, struct http_qarg *qarg_spec) {
// our return code
int error = -1;
// get the uri from the request
const char *uri = evhttp_request_get_uri(request);
// the keyval list that we get from evhttp_parse_query
struct evkeyval *qarg;
struct evkeyvalq qargs;
// parse the uri into a list
evhttp_parse_query(uri, &qargs);
// the http_qarg that we iterate with
struct http_qarg *qarg_info;
// iterate over the list of given query arugments
TAILQ_FOREACH(qarg, &qargs, next) {
// match them against our http_qarg structs
for (qarg_info = qarg_spec; qarg_info->hqa_type != QARG_END; qarg_info++) {
if (strcmp(qarg->key, qarg_info->hqa_key) == 0) {
// found a match
// extract a value from the qarg
char *cptr = NULL;
unsigned long long int uint_val;
switch (qarg_info->hqa_type) {
case QARG_UINT16 :
case QARG_UINT32 :
case QARG_UINT64 :
uint_val = strtoull(qarg->value, &cptr, 10);
if (
(*qarg->value == '\0' || *cptr != '\0')
|| (qarg_info->hqa_type == QARG_UINT16 && uint_val > SHRT_MAX)
|| (qarg_info->hqa_type == QARG_UINT32 && uint_val > UINT_MAX)
|| (qarg_info->hqa_type == QARG_UINT64 && uint_val > ULLONG_MAX)
)
ERROR("invalid QARG_UINT: %s: %s -> %lld", qarg->key, qarg->value, uint_val);
if (qarg_info->hqa_type == QARG_UINT16)
*((unsigned short int *) qarg_info->hqa_addr) = (unsigned short int) uint_val;
else if (qarg_info->hqa_type == QARG_UINT32)
*((unsigned int *) qarg_info->hqa_addr) = (unsigned int) uint_val;
else if (qarg_info->hqa_type == QARG_UINT64)
*((unsigned long long int *) qarg_info->hqa_addr) = (unsigned long long int) uint_val;
else
assert(0);
break;
case QARG_INVALID :
ERROR("QARG_INVALID: %s: %s", qarg->key, qarg->value);
default :
FATAL("invalid qarg_info->hqa_type: %d", qarg_info->hqa_type);
}
// clear the QARG_REQUIRED flag
qarg_info->hqa_flags &= ~QARG_REQUIRED;
}
}
}
// missing qargs?
for (qarg_info = qarg_spec; qarg_info->hqa_type != QARG_END; qarg_info++) {
if (qarg_info->hqa_flags & QARG_REQUIRED)
ERROR("missing value for required qarg: %s", qarg_info->hqa_key);
}
// success
error = 0;
error:
// clean up the qargs (badly named functions :< )
evhttp_clear_headers(&qargs);
return error;
}