X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-hreq.c;h=e45b25031a99cce7e9dd84ffc375a94b446f8385;hb=94014f46d4751492133f65b12f1dea1cfa36d021;hp=7c481e957433255bae7b9fed14c66557f093b952;hpb=c0453c34a58aac8150300ab829149a0ca4d9e5ee;p=src%2Fapp-framework-binder.git diff --git a/src/afb-hreq.c b/src/afb-hreq.c index 7c481e95..e45b2503 100644 --- a/src/afb-hreq.c +++ b/src/afb-hreq.c @@ -27,13 +27,15 @@ #include #include +#include #if defined(USE_MAGIC_MIME_TYPE) #include #endif -#include "local-def.h" #include "afb-method.h" +#include "afb-websock.h" +#include "afb-apis.h" #include "afb-req-itf.h" #include "afb-hreq.h" #include "session.h" @@ -55,9 +57,9 @@ 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 afb_arg req_get(struct afb_hreq *hreq, const char *name); @@ -312,15 +314,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 +382,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); @@ -399,6 +410,68 @@ int afb_hreq_redirect_to(struct afb_hreq *hreq, const char *url) return 1; } +int afb_hreq_one_page_api_redirect( + struct afb_hreq *hreq, + void *data) +{ + size_t plen; + char *url; + + if (hreq->lentail >= 2 && hreq->tail[1] == '#') + return 0; + /* + * Here we have for example: + * url = "/pre/dir/page" lenurl = 13 + * tail = "/dir/page" lentail = 9 + * + * We will produce "/pre/#!dir/page" + * + * Let compute plen that include the / at end (for "/pre/") + */ + plen = hreq->lenurl - hreq->lentail + 1; + url = alloca(hreq->lenurl + 3); + memcpy(url, hreq->url, plen); + url[plen++] = '#'; + url[plen++] = '!'; + memcpy(&url[plen], &hreq->tail[1], hreq->lentail); + return afb_hreq_redirect_to(hreq, url); +} + +int afb_hreq_websocket_switch(struct afb_hreq *hreq, void *data) +{ + int later; + + afb_hreq_context(hreq); + if (hreq->lentail != 0 || !afb_websock_check(hreq, &later)) + return 0; + + if (!later) { + struct afb_websock *ws = afb_websock_create(hreq); + if (ws != NULL) + hreq->upgrade = 1; + } + return 1; +} + +int afb_hreq_rest_api(struct afb_hreq *hreq, void *data) +{ + const char *api, *verb; + size_t lenapi, lenverb; + struct AFB_clientCtx *context; + + api = &hreq->tail[strspn(hreq->tail, "/")]; + lenapi = strcspn(api, "/"); + verb = &api[lenapi]; + verb = &verb[strspn(verb, "/")]; + lenverb = strcspn(verb, "/"); + + if (!(*api && *verb && lenapi && lenverb)) + return 0; + + context = afb_hreq_context(hreq); + return afb_apis_handle(afb_hreq_to_req(hreq), context, api, lenapi, verb, lenverb); +} + const char *afb_hreq_get_cookie(struct afb_hreq *hreq, const char *name) { return MHD_lookup_connection_value(hreq->connection, MHD_COOKIE_KIND, name); @@ -415,23 +488,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,59 +506,55 @@ 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); +fprintf(stderr, "%s=%s %s=%s %s\n",key,hdat->key,file,hdat->value,hdat->path); if (hdat->value == NULL) { - hdat->file = open(file, O_WRONLY|O_TRUNC|O_CREAT, 0600); - if (hdat->file == 0) { - hdat->file = dup(0); - close(0); - } - if (hdat->file <= 0) { - hdat->file = 0; - return 0; - } hdat->value = strdup(file); - if (hdat->value == NULL) { - close(hdat->file); - hdat->file = 0; + if (hdat->value == NULL) return 0; - } + fd = opentempfile(&hdat->path); + } else if (strcmp(hdat->value, file) || hdat->path == NULL) { + return 0; } else { - if (strcmp(hdat->value, file)) - return 0; - } - 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; + fd = open(hdat->path, O_WRONLY|O_APPEND); } + if (fd < 0) + return 0; while (size) { - sz = write(hdat->file, data, size); + sz = write(fd, data, size); if (sz >= 0) { hdat->length += (size_t)sz; size -= (size_t)sz; data += sz; } else if (errno != EINTR) - return 0; + break; } - return 1; -} - -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; + close(fd); + return !size; } - struct afb_req afb_hreq_to_req(struct afb_hreq *hreq) { return (struct afb_req){ .itf = &afb_hreq_itf, .data = hreq }; @@ -511,14 +568,14 @@ static struct afb_arg req_get(struct afb_hreq *hreq, const char *name) .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 }; } @@ -535,9 +592,9 @@ static int _iterargs_(struct iterdata *id, enum MHD_ValueKind kind, const char * return 1; return id->iterator(id->closure, (struct afb_arg){ .name = key, - .value = value, - .size = 0, - .is_file = 0 + .value = value ? : "", + .size = value ? strlen(value) : 0, + .path = NULL }); } @@ -550,7 +607,7 @@ static void req_iterate(struct afb_hreq *hreq, int (*iterator)(void *closure, st .name = hdat->key, .value = hdat->value, .size = hdat->length, - .is_file = (hdat->file != 0)})) + .path = hdat->path})) return; hdat = hdat->next; }