From 22b796ae268478204aef55b12c17db74a30ccadf Mon Sep 17 00:00:00 2001 From: ThoNohT Date: Tue, 19 May 2026 14:46:24 +0200 Subject: [PATCH] Implement get handler --- src/get_handler.c | 34 ++++++++++++++++++++---- src/main.c | 13 +++++++++- src/opds_handler.c | 65 +++++++++++++++++++++++----------------------- 3 files changed, 74 insertions(+), 38 deletions(-) diff --git a/src/get_handler.c b/src/get_handler.c index 86ee33c..cef849f 100644 --- a/src/get_handler.c +++ b/src/get_handler.c @@ -1,6 +1,30 @@ -static enum MHD_Result handle_get(struct MHD_Connection *connection, SV url, SV base_path, SV username) { - (void)url; - (void)username; - (void)base_path; - return send_response(connection, 200, sv("TODO: Get\n"), false); +static enum MHD_Result handle_get(struct MHD_Connection *connection, SV url, Settings settings, SV username) { + noh_arena_save(&temp); + Noh_String fs_path = build_path(false, &settings.base_path, &username, &url); + + noh_log(NOH_INFO, "Physical path: "Nsv_Fmt, Nsv_Arg(fs_path)); + + if (!noh_sv_ends_with(noh_sv_from_string(fs_path), sv(".epub"))) { + return send_response(connection, 400, sv("File is not an epub file."), false); + } + + noh_string_append_null(&fs_path); + + // Try to open the file. + FILE *file = fopen(fs_path.elems, "r"); + if (file == NULL) { + if (errno == ENOENT) { + noh_arena_reset(&temp); + return send_response(connection, 404, sv("File does not exist."), false); + } else { + noh_log(NOH_ERROR, "Opening file failed."); + noh_arena_reset(&temp); + return send_response(connection, 500, sv(""), false); + } + } + + fseek(file, 0L, SEEK_END); + size_t file_size = ftell(file); + fseek(file, 0L, SEEK_SET); + return send_epub_file(connection, fileno(file), file_size); } diff --git a/src/main.c b/src/main.c index 0d7aa92..6b3f336 100644 --- a/src/main.c +++ b/src/main.c @@ -36,6 +36,17 @@ static enum MHD_Result send_response(struct MHD_Connection *connection, int stat return ret; } +static enum MHD_Result send_epub_file(struct MHD_Connection *connection, int file, size_t size) { + struct MHD_Response *response = MHD_create_response_from_fd(size, file); + if (!response) return MHD_NO; + + MHD_add_response_header(response, "content-type", "application/epub+zip"); + + enum MHD_Result ret = MHD_queue_response(connection, 200, response); + MHD_destroy_response(response); + return ret; +} + #include "opds_handler.c" #include "get_handler.c" @@ -76,7 +87,7 @@ static enum MHD_Result request_handler( SV controller = noh_sv_chop_by_delim(&url, '/'); if (noh_sv_eq_ci(controller, sv("opds"))) return handle_opds(connection, url, settings, username); - if (noh_sv_eq_ci(controller, sv("get"))) return handle_get(connection, url, settings.base_path, username); + if (noh_sv_eq_ci(controller, sv("get"))) return handle_get(connection, url, settings, username); return send_response(connection, 404, sv(""), false); } diff --git a/src/opds_handler.c b/src/opds_handler.c index 1836849..a2a2bbf 100644 --- a/src/opds_handler.c +++ b/src/opds_handler.c @@ -62,39 +62,40 @@ static enum MHD_Result handle_opds(struct MHD_Connection *connection, SV url, Se noh_log(NOH_INFO, "Physical path: "Nsv_Fmt, Nsv_Arg(self_entry.full_path)); DIR *dir = opendir(fs_path_cstr.elems); - if (dir) { - Library_Entries list = {0}; + if (!dir) { + if (errno == ENOENT) { + closedir(dir); + noh_arena_reset(&temp); + return send_response(connection, 404, sv(""), false); - // Build up list of entries. - struct dirent *entry = noh_arena_alloc(&temp, sizeof(struct dirent)); - while ((entry = readdir(dir)) != NULL) { - Library_Entry result = {0}; - if (create_entry(entry, fs_path_cstr.elems, &result)) noh_da_append(&list, result); + } else { + noh_log(NOH_ERROR, "Opening directory failed."); + noh_arena_reset(&temp); + return send_response(connection, 500, sv(""), false); } - - // Sort entries, folders first, then by name. - if (list.count > 1) qsort(list.elems, list.count, sizeof(list.elems[0]), compare_library_entries); - - // Create and send response. - Noh_String response = create_feed_response(self_entry, url, list); - bool result = send_response(connection, 200, noh_sv_from_string(response), true); - - // Cleanup. - noh_da_free(&list); - noh_string_free(&response); - noh_arena_reset(&temp); - closedir(dir); - - return result; - - } else if (errno == ENOENT) { - closedir(dir); - noh_arena_reset(&temp); - return send_response(connection, 404, sv(""), false); - - } else { - noh_log(NOH_ERROR, "Opening directory failed."); - noh_arena_reset(&temp); - return send_response(connection, 500, sv(""), false); } + + Library_Entries list = {0}; + + // Build up list of entries. + struct dirent *entry = noh_arena_alloc(&temp, sizeof(struct dirent)); + while ((entry = readdir(dir)) != NULL) { + Library_Entry result = {0}; + if (create_entry(entry, fs_path_cstr.elems, &result)) noh_da_append(&list, result); + } + + // Sort entries, folders first, then by name. + if (list.count > 1) qsort(list.elems, list.count, sizeof(list.elems[0]), compare_library_entries); + + // Create and send response. + Noh_String response = create_feed_response(self_entry, url, list); + bool result = send_response(connection, 200, noh_sv_from_string(response), true); + + // Cleanup. + noh_da_free(&list); + noh_string_free(&response); + noh_arena_reset(&temp); + closedir(dir); + + return result; }