From c5eac5d27fb3967d796fe3c75f4cc1bdcd18ed01 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Wed, 10 Aug 2022 21:00:32 +0200 Subject: file: support using dynamic script handlers as error pages Rework the current request handler code to not require an error page path to be an actual file system entity. Signed-off-by: Jo-Philipp Wich --- file.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/file.c b/file.c index 1548900..ac781c1 100644 --- a/file.c +++ b/file.c @@ -49,6 +49,7 @@ struct deferred_request { struct dispatch_handler *d; struct client *cl; struct path_info pi; + char *url; bool called, path; }; @@ -631,7 +632,7 @@ static void uh_file_data(struct client *cl, struct path_info *pi, int fd) file_write_cb(cl); } -static bool __handle_file_request(struct client *cl, char *url); +static bool __handle_file_request(struct client *cl, char *url, bool is_error_handler); static void uh_file_request(struct client *cl, const char *url, struct path_info *pi, struct blob_attr **tb) @@ -684,7 +685,7 @@ error: req->redirect_status = 403; error_handler = alloca(strlen(conf.error_handler) + 1); strcpy(error_handler, conf.error_handler); - if (__handle_file_request(cl, error_handler)) + if (__handle_file_request(cl, error_handler, true)) return; } @@ -728,10 +729,8 @@ dispatch_find(const char *url, struct path_info *pi) } static void -uh_invoke_script(struct client *cl, struct dispatch_handler *d, struct path_info *pi) +uh_invoke_script(struct client *cl, struct dispatch_handler *d, char *url, struct path_info *pi) { - char *url = blobmsg_data(blob_data(cl->hdr.head)); - n_requests++; d->handle_request(cl, url, pi); } @@ -752,7 +751,7 @@ static void uh_complete_request(struct client *cl) cl = dr->cl; dr->called = true; cl->dispatch.data_blocked = false; - uh_invoke_script(cl, dr->d, dr->path ? &dr->pi : NULL); + uh_invoke_script(cl, dr->d, dr->url, dr->path ? &dr->pi : NULL); client_poll_post_data(cl); ustream_poll(cl->us); } @@ -787,10 +786,10 @@ static int field_len(const char *ptr) _field(query) static void -uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info *pi) +uh_defer_script(struct client *cl, struct dispatch_handler *d, char *url, struct path_info *pi) { struct deferred_request *dr; - char *_root, *_phys, *_name, *_info, *_query; + char *_url, *_root, *_phys, *_name, *_info, *_query; cl->dispatch.req_free = uh_free_pending_request; @@ -798,7 +797,7 @@ uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info /* allocate enough memory to duplicate all path_info strings in one block */ #undef _field #define _field(_name) &_##_name, field_len(pi->_name), - dr = calloc_a(sizeof(*dr), path_info_fields NULL); + dr = calloc_a(sizeof(*dr), &_url, strlen(url), path_info_fields NULL); memcpy(&dr->pi, pi, sizeof(*pi)); dr->path = true; @@ -808,11 +807,12 @@ uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info #define _field(_name) if (pi->_name) dr->pi._name = strcpy(_##_name, pi->_name); path_info_fields } else { - dr = calloc(1, sizeof(*dr)); + dr = calloc_a(sizeof(*dr), &_url, strlen(url), NULL); } cl->dispatch.req_data = dr; cl->dispatch.data_blocked = true; + dr->url = strcpy(_url, url); dr->cl = cl; dr->d = d; list_add(&dr->list, &pending_requests); @@ -825,13 +825,13 @@ uh_invoke_handler(struct client *cl, struct dispatch_handler *d, char *url, stru return d->handle_request(cl, url, pi); if (n_requests >= conf.max_script_requests) - return uh_defer_script(cl, d, pi); + return uh_defer_script(cl, d, url, pi); cl->dispatch.req_free = uh_complete_request; - uh_invoke_script(cl, d, pi); + uh_invoke_script(cl, d, url, pi); } -static bool __handle_file_request(struct client *cl, char *url) +static bool __handle_file_request(struct client *cl, char *url, bool is_error_handler) { static const struct blobmsg_policy hdr_policy[__HDR_MAX] = { [HDR_AUTHORIZATION] = { "authorization", BLOBMSG_TYPE_STRING }, @@ -846,6 +846,16 @@ static bool __handle_file_request(struct client *cl, char *url) struct path_info *pi; char *user, *pass, *auth; + if (is_error_handler) { + d = dispatch_find(url, NULL); + + if (d) { + uh_invoke_handler(cl, d, url, NULL); + + return true; + } + } + pi = uh_path_lookup(cl, url); if (!pi) return false; @@ -931,7 +941,7 @@ void uh_handle_request(struct client *cl) if (d) return uh_invoke_handler(cl, d, url, NULL); - if (__handle_file_request(cl, url)) + if (__handle_file_request(cl, url, false)) return; if (uh_handler_run(cl, &url, true)) { @@ -939,7 +949,7 @@ void uh_handle_request(struct client *cl) return; uh_handler_run(cl, &url, false); - if (__handle_file_request(cl, url)) + if (__handle_file_request(cl, url, false)) return; } @@ -947,7 +957,7 @@ void uh_handle_request(struct client *cl) if (conf.error_handler) { error_handler = alloca(strlen(conf.error_handler) + 1); strcpy(error_handler, conf.error_handler); - if (__handle_file_request(cl, error_handler)) + if (__handle_file_request(cl, error_handler, true)) return; } -- cgit v1.2.1