#include "afb-req-itf.h"
#include "afb-hreq.h"
-static char empty_string[1] = "";
+static char empty_string[] = "";
+struct hreq_data {
+ struct hreq_data *next;
+ char *key;
+ int file;
+ size_t length;
+ char *value;
+};
+
+static const struct afb_req_itf afb_hreq_itf = {
+ .argument = (void*)afb_hreq_get_argument,
+ .is_argument_file = (void*)afb_hreq_is_argument_a_file,
+ .iterate_arguments = (void*)afb_hreq_iterate_arguments
+};
+
+static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create)
+{
+ struct hreq_data *data = hreq->data;
+ if (key == NULL)
+ key = empty_string;
+ while (data != NULL) {
+ if (!strcasecmp(data->key, key))
+ return data;
+ data = data->next;
+ }
+ if (create) {
+ data = calloc(1, sizeof *data);
+ if (data != NULL) {
+ data->key = strdup(key);
+ if (data->key == NULL) {
+ free(data);
+ data = NULL;
+ } else {
+ data->next = hreq->data;
+ hreq->data = data;
+ }
+ }
+ }
+ return data;
+}
/* a valid subpath is a relative path not looking deeper than root using .. */
static int validsubpath(const char *subpath)
const char *afb_hreq_get_argument(struct afb_hreq *hreq, const char *name)
{
- return MHD_lookup_connection_value(hreq->connection, MHD_GET_ARGUMENT_KIND, name);
+ struct hreq_data *data = get_data(hreq, name, 0);
+ return data ? data->value : MHD_lookup_connection_value(hreq->connection, MHD_GET_ARGUMENT_KIND, name);
}
const char *afb_hreq_get_header(struct afb_hreq *hreq, const char *name)
return MHD_lookup_connection_value(hreq->connection, MHD_HEADER_KIND, name);
}
-struct afb_req_itf afb_hreq_itf = {
- .get_cookie = (void*)afb_hreq_get_cookie,
- .get_argument = (void*)afb_hreq_get_argument
+void afb_hreq_post_end(struct afb_hreq *hreq)
+{
+ struct hreq_data *data = hreq->data;
+ while(data) {
+ if (data->file > 0) {
+ close(data->file);
+ data->file = -1;
+ }
+ data = data->next;
+ }
+}
+
+int afb_hreq_post_add(struct afb_hreq *hreq, const char *key, const char *data, size_t size)
+{
+ void *p;
+ struct hreq_data *hdat = get_data(hreq, key, 1);
+ if (hdat->file) {
+ return 0;
+ }
+ p = realloc(hdat->value, hdat->length + size + 1);
+ if (p == NULL) {
+ return 0;
+ }
+ hdat->value = p;
+ memcpy(&hdat->value[hdat->length], data, size);
+ hdat->length += size;
+ hdat->value[hdat->length] = 0;
+ return 1;
+}
+
+int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *file, const char *data, size_t size)
+{
+ struct hreq_data *hdat = get_data(hreq, key, 1);
+
+ /* continuation with reopening */
+ if (hdat->file < 0) {
+ hdat->file = open(hdat->value, O_WRONLY|O_APPEND);
+ if (hdat->file == 0) {
+ hdat->file = dup(0);
+ close(0);
+ }
+ if (hdat->file <= 0)
+ return 0;
+ }
+ if (hdat->file > 0) {
+ write(hdat->file, data, size);
+ return 1;
+ }
+
+ /* creation */
+ /* TODO */
+ return 0;
+
+}
+
+int afb_hreq_is_argument_a_file(struct afb_hreq *hreq, const char *key)
+{
+ struct hreq_data *hdat = get_data(hreq, key, 0);
+ return hdat != NULL && hdat->file != 0;
+}
+
+
+struct afb_req afb_hreq_to_req(struct afb_hreq *hreq)
+{
+ return (struct afb_req){ .itf = &afb_hreq_itf, .data = hreq };
+}
+
+struct iterator_data
+{
+ struct afb_hreq *hreq;
+ int (*iterator)(void *closure, const char *key, const char *value, int isfile);
+ void *closure;
};
+static int itargs(struct iterator_data *id, enum MHD_ValueKind kind, const char *key, const char *value)
+{
+ if (get_data(id->hreq, key, 0))
+ return 1;
+ return id->iterator(id->closure, key, value, 0);
+}
+
+void afb_hreq_iterate_arguments(struct afb_hreq *hreq, int (*iterator)(void *closure, const char *key, const char *value, int isfile), void *closure)
+{
+ struct iterator_data id = { .hreq = hreq, .iterator = iterator, .closure = closure };
+ struct hreq_data *data = hreq->data;
+ while (data) {
+ if (!iterator(closure, data->key, data->value, !!data->file))
+ return;
+ data = data->next;
+ }
+ MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)itargs, &id);
+}
+
+void afb_hreq_drop_data(struct afb_hreq *hreq)
+{
+ struct hreq_data *data = hreq->data;
+ while (data) {
+ hreq->data = data->next;
+ free(data->key);
+ free(data->value);
+ free(data);
+ data = hreq->data;
+ }
+}
+