X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-hreq.c;h=3ddc4d1e8a00cc7a576796515024619bd6e0d09d;hb=041ce4919b4513f7e019b018558e947164101b35;hp=474b90e8f2adecdbf4a1a202c3ca9ba011fa6e08;hpb=b75bbfd9bd96ad8bb7174a768ae70cf3e8c5af7a;p=src%2Fapp-framework-binder.git diff --git a/src/afb-hreq.c b/src/afb-hreq.c index 474b90e8..3ddc4d1e 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -27,12 +27,12 @@ #include #include +#include #if defined(USE_MAGIC_MIME_TYPE) #include #endif -#include "local-def.h" #include "afb-method.h" #include "afb-req-itf.h" #include "afb-hreq.h" @@ -55,24 +55,28 @@ static const char token_cookie[] = "token"; struct hreq_data { struct hreq_data *next; char *key; - int file; size_t length; char *value; + char *path; }; +static struct json_object *req_json(struct afb_hreq *hreq); static struct afb_arg req_get(struct afb_hreq *hreq, const char *name); -static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure); static void req_fail(struct afb_hreq *hreq, const char *status, const char *info); static void req_success(struct afb_hreq *hreq, json_object *obj, const char *info); +static const char *req_raw(struct afb_hreq *hreq, size_t *size); +static void req_send(struct afb_hreq *hreq, char *buffer, size_t size); static int req_session_create(struct afb_hreq *hreq); static int req_session_check(struct afb_hreq *hreq, int refresh); static void req_session_close(struct afb_hreq *hreq); static const struct afb_req_itf afb_hreq_itf = { + .json = (void*)req_json, .get = (void*)req_get, - .iterate = (void*)req_iterate, - .fail = (void*)req_fail, .success = (void*)req_success, + .fail = (void*)req_fail, + .raw = (void*)req_raw, + .send = (void*)req_send, .session_create = (void*)req_session_create, .session_check = (void*)req_session_check, .session_close = (void*)req_session_close @@ -81,8 +85,6 @@ static const struct afb_req_itf afb_hreq_itf = { 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; @@ -221,11 +223,16 @@ void afb_hreq_free(struct afb_hreq *hreq) MHD_destroy_post_processor(hreq->postform); for (data = hreq->data; data; data = hreq->data) { hreq->data = data->next; + if (data->path) { + unlink(data->path); + free(data->path); + } free(data->key); free(data->value); free(data); } ctxClientPut(hreq->context); + json_object_put(hreq->json); free(hreq); } } @@ -312,15 +319,24 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f /* serve directory */ if (S_ISDIR(st.st_mode)) { - if (hreq->url[hreq->lenurl - 1] != '/') { - /* the redirect is needed for reliability of relative path */ - char *tourl = alloca(hreq->lenurl + 2); - memcpy(tourl, hreq->url, hreq->lenurl); - tourl[hreq->lenurl] = '/'; - tourl[hreq->lenurl + 1] = 0; - rc = afb_hreq_redirect_to(hreq, tourl); - } else { - rc = afb_hreq_reply_file_if_exist(hreq, fd, "index.html"); + static const char *indexes[] = { "index.html", NULL }; + int i = 0; + rc = 0; + while (indexes[i] != NULL) { + if (faccessat(fd, indexes[i], R_OK, 0) == 0) { + if (hreq->url[hreq->lenurl - 1] != '/') { + /* the redirect is needed for reliability of relative path */ + char *tourl = alloca(hreq->lenurl + 2); + memcpy(tourl, hreq->url, hreq->lenurl); + tourl[hreq->lenurl] = '/'; + tourl[hreq->lenurl + 1] = 0; + rc = afb_hreq_redirect_to(hreq, tourl); + } else { + rc = afb_hreq_reply_file_if_exist(hreq, fd, indexes[i]); + } + break; + } + i++; } close(fd); return rc; @@ -371,7 +387,7 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f } /* fills the value and send */ - MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, hreq->session->cacheTimeout); + MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, hreq->cacheTimeout); MHD_add_response_header(response, MHD_HTTP_HEADER_ETAG, etag); MHD_queue_response(hreq->connection, status, response); MHD_destroy_response(response); @@ -415,23 +431,11 @@ const char *afb_hreq_get_header(struct afb_hreq *hreq, const char *name) return MHD_lookup_connection_value(hreq->connection, MHD_HEADER_KIND, name); } -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) { + if (hdat->path != NULL) { return 0; } p = realloc(hdat->value, hdat->length + size + 1); @@ -445,38 +449,54 @@ int afb_hreq_post_add(struct afb_hreq *hreq, const char *key, const char *data, return 1; } +static int opentempfile(char **path) +{ + int fd; + char *fname; + + fname = strdup("XXXXXX"); /* TODO improve the path */ + if (fname == NULL) + return -1; + + fd = mkostemp(fname, O_CLOEXEC|O_WRONLY); + if (fd < 0) + free(fname); + else + *path = fname; + return fd; +} + int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *file, const char *data, size_t size) { + int fd; + ssize_t sz; 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) + if (hdat->value == NULL) { + hdat->value = strdup(file); + if (hdat->value == NULL) return 0; + fd = opentempfile(&hdat->path); + } else if (strcmp(hdat->value, file) || hdat->path == NULL) { + return 0; + } else { + fd = open(hdat->path, O_WRONLY|O_APPEND); } - if (hdat->file > 0) { - write(hdat->file, data, size); - return 1; + if (fd < 0) + return 0; + while (size) { + sz = write(fd, data, size); + if (sz >= 0) { + hdat->length += (size_t)sz; + size -= (size_t)sz; + data += sz; + } else if (errno != EINTR) + break; } - - /* creation */ - /* TODO */ - return 0; - + close(fd); + return !size; } -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 }; @@ -489,51 +509,63 @@ static struct afb_arg req_get(struct afb_hreq *hreq, const char *name) return (struct afb_arg){ .name = hdat->key, .value = hdat->value, - .size = hdat->length, - .is_file = (hdat->file != 0) + .path = hdat->path }; return (struct afb_arg){ .name = name, .value = MHD_lookup_connection_value(hreq->connection, MHD_GET_ARGUMENT_KIND, name), - .size = 0, - .is_file = 0 + .path = NULL }; } -struct iterdata +static int _iterargs_(struct json_object *obj, enum MHD_ValueKind kind, const char *key, const char *value) { - struct afb_hreq *hreq; - int (*iterator)(void *closure, struct afb_arg arg); - void *closure; -}; + json_object_object_add(obj, key, value ? json_object_new_string(value) : NULL); + return 1; +} -static int _iterargs_(struct iterdata *id, enum MHD_ValueKind kind, const char *key, const char *value) +static struct json_object *req_json(struct afb_hreq *hreq) { - if (get_data(id->hreq, key, 0)) - return 1; - return id->iterator(id->closure, (struct afb_arg){ - .name = key, - .value = value, - .size = 0, - .is_file = 0 - }); + struct hreq_data *hdat; + struct json_object *obj, *val; + + obj = hreq->json; + if (obj == NULL) { + hreq->json = obj = json_object_new_object(); + if (obj == NULL) { + } else { + MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)_iterargs_, obj); + for (hdat = hreq->data ; hdat ; hdat = hdat->next) { + if (hdat->path == NULL) + val = hdat->value ? json_object_new_string(hdat->value) : NULL; + else { + val = json_object_new_object(); + if (val == NULL) { + } else { + json_object_object_add(val, "file", json_object_new_string(hdat->value)); + json_object_object_add(val, "path", json_object_new_string(hdat->path)); + } + } + json_object_object_add(obj, hdat->key, val); + } + } + } + return obj; } -static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, struct afb_arg arg), void *closure) +static const char *req_raw(struct afb_hreq *hreq, size_t *size) { - struct iterdata id = { .hreq = hreq, .iterator = iterator, .closure = closure }; - struct hreq_data *hdat = hreq->data; - while (hdat) { - if (!iterator(closure, (struct afb_arg){ - .name = hdat->key, - .value = hdat->value, - .size = hdat->length, - .is_file = (hdat->file != 0)})) - return; - hdat = hdat->next; - } - MHD_get_connection_values (hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)_iterargs_, &id); + const char *result = json_object_get_string(req_json(hreq)); + *size = result ? strlen(result) : 0; + return result; +} + +static void req_send(struct afb_hreq *hreq, char *buffer, size_t size) +{ + struct MHD_Response *response = MHD_create_response_from_buffer((unsigned)size, buffer, MHD_RESPMEM_MUST_FREE); + MHD_queue_response(hreq->connection, MHD_HTTP_OK, response); + MHD_destroy_response(response); } static ssize_t send_json_cb(json_object *obj, uint64_t pos, char *buf, size_t max)