From 67f59e1354b5c435c64ac6858f93fffed8ae1236 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Wed, 30 Oct 2024 14:17:49 +0900 Subject: [PATCH] Add option --enable-static-dir=, use static --- example_config/example.config | 2 + example_config/silly.jpg | Bin 0 -> 15939 bytes src/arg_parse.c | 24 ++++++ src/arg_parse.h | 3 + src/http.c | 11 ++- src/http.h | 3 +- src/main.c | 139 ++++++++++++++++++++++++++++------ 7 files changed, 156 insertions(+), 26 deletions(-) create mode 100644 example_config/silly.jpg diff --git a/example_config/example.config b/example_config/example.config index 768af8c..2754095 100644 --- a/example_config/example.config +++ b/example_config/example.config @@ -69,6 +69,8 @@ HTML='''

Nested inner: further

{{{VAR}}}
+ +
back diff --git a/example_config/silly.jpg b/example_config/silly.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d2c737197ab6b5af25645c6a35a5044903bd4c10 GIT binary patch literal 15939 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"); puts(" --cache-entry-lifetime-seconds="); + puts(" --enable-static-dir="); } Args parse_args(int32_t argc, char **argv) { @@ -128,6 +129,29 @@ Args parse_args(int32_t argc, char **argv) { "NOTICE set cache-entry-lifetime to %lu\n", args.cache_lifespan_seconds); } + } else if (strncmp(argv[0], "--enable-static-dir=", 20) == 0) { + args.static_dir = argv[0] + 20; + // Check if it actually is an existing directory. + DIR *d = opendir(args.static_dir); + if (d == NULL) { + if (errno == ENOENT) { + fprintf( + stderr, + "ERROR Directory \"%s\" does not exist!\n", + args.static_dir); + exit(1); + } else { + fprintf( + stderr, + "ERROR Failed to open directory \"%s\" (errno %d)!\n", + args.static_dir, + errno); + exit(1); + } + } else { + printf("Directory \"%s\" exists.\n", args.static_dir); + } + closedir(d); } else { fprintf(stderr, "ERROR: Invalid args!\n"); print_usage(); diff --git a/src/arg_parse.h b/src/arg_parse.h index 24ba5f7..7595f72 100644 --- a/src/arg_parse.h +++ b/src/arg_parse.h @@ -38,6 +38,9 @@ typedef struct Args { // Does not need to be free'd since it points to a string in argv. const char *cache_dir; size_t cache_lifespan_seconds; + // Non-NULL if static-dir is specified and files in the dir are to be served. + // Does not need to be free'd since it points to a string in argv. + const char *static_dir; } Args; void print_usage(void); diff --git a/src/http.c b/src/http.c index 0e688aa..958b012 100644 --- a/src/http.c +++ b/src/http.c @@ -65,7 +65,8 @@ char *c_simple_http_request_response( C_SIMPLE_HTTP_HTTPTemplates *templates, size_t *out_size, enum C_SIMPLE_HTTP_ResponseCode *out_response_code, - const Args *args) { + const Args *args, + char **request_path_out) { if (out_size) { *out_size = 0; } @@ -176,6 +177,11 @@ char *c_simple_http_request_response( char *generated_buf = NULL; + if (request_path_out) { + *request_path_out = + strdup(stripped_path ? stripped_path : request_path_unescaped); + } + if (args->cache_dir) { int ret = c_simple_http_cache_path( stripped_path ? stripped_path : request_path_unescaped, @@ -212,7 +218,8 @@ char *c_simple_http_request_response( } if (!generated_buf || generated_size == 0) { - fprintf(stderr, "ERROR Unable to generate response html for path \"%s\"!\n", + fprintf(stderr, + "WARNING Unable to generate response html for path \"%s\"!\n", request_path); if (out_response_code) { if ( diff --git a/src/http.h b/src/http.h index 7b7a52a..018f065 100644 --- a/src/http.h +++ b/src/http.h @@ -50,7 +50,8 @@ char *c_simple_http_request_response( C_SIMPLE_HTTP_HTTPTemplates *templates, size_t *out_size, enum C_SIMPLE_HTTP_ResponseCode *out_response_code, - const Args *args + const Args *args, + char **request_path_out ); /// Takes a PATH string and returns a "bare" path. diff --git a/src/main.c b/src/main.c index 976f245..92b7b5b 100644 --- a/src/main.c +++ b/src/main.c @@ -42,8 +42,16 @@ #include "constants.h" #include "http.h" #include "helpers.h" +#include "static.h" #define CHECK_ERROR_WRITE(write_expr) \ + if (write_expr < 0) { \ + close(connection_fd); \ + fprintf(stderr, "ERROR Failed to write to connected peer, closing...\n"); \ + return 1; \ + } + +#define CHECK_ERROR_WRITE_CONTINUE(write_expr) \ if (write_expr < 0) { \ close(connection_fd); \ fprintf(stderr, "ERROR Failed to write to connected peer, closing...\n"); \ @@ -74,6 +82,31 @@ void c_simple_http_inotify_fd_cleanup(int *fd) { } } +int c_simple_http_on_error( + enum C_SIMPLE_HTTP_ResponseCode response_code, + int connection_fd +) { + const char *response = c_simple_http_response_code_error_to_response( + response_code); + size_t response_size; + if (response) { + response_size = strlen(response); + CHECK_ERROR_WRITE(write(connection_fd, response, response_size)); + } else { + CHECK_ERROR_WRITE(write( + connection_fd, "HTTP/1.1 500 Internal Server Error\n", 35)); + CHECK_ERROR_WRITE(write(connection_fd, "Allow: GET\n", 11)); + CHECK_ERROR_WRITE(write(connection_fd, "Connection: close\n", 18)); + CHECK_ERROR_WRITE(write( + connection_fd, "Content-Type: text/html\n", 24)); + CHECK_ERROR_WRITE(write(connection_fd, "Content-Length: 35\n", 19)); + CHECK_ERROR_WRITE(write( + connection_fd, "\n

500 Internal Server Error

\n", 36)); + } + + return 0; +} + int main(int argc, char **argv) { __attribute__((cleanup(c_simple_http_free_args))) Args args = parse_args(argc, argv); @@ -354,18 +387,23 @@ int main(int argc, char **argv) { size_t response_size = 0; enum C_SIMPLE_HTTP_ResponseCode response_code; + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *request_path = NULL; const char *response = c_simple_http_request_response( (const char*)recv_buf, (uint32_t)read_ret, &parsed_config, &response_size, &response_code, - &args); + &args, + &request_path); if (response && response_code == C_SIMPLE_HTTP_Response_200_OK) { - CHECK_ERROR_WRITE(write(connection_fd, "HTTP/1.1 200 OK\n", 16)); - CHECK_ERROR_WRITE(write(connection_fd, "Allow: GET\n", 11)); - CHECK_ERROR_WRITE(write(connection_fd, "Connection: close\n", 18)); - CHECK_ERROR_WRITE(write( + CHECK_ERROR_WRITE_CONTINUE(write( + connection_fd, "HTTP/1.1 200 OK\n", 16)); + CHECK_ERROR_WRITE_CONTINUE(write(connection_fd, "Allow: GET\n", 11)); + CHECK_ERROR_WRITE_CONTINUE(write( + connection_fd, "Connection: close\n", 18)); + CHECK_ERROR_WRITE_CONTINUE(write( connection_fd, "Content-Type: text/html\n", 24)); char content_length_buf[128]; size_t content_length_buf_size = 0; @@ -386,28 +424,83 @@ int main(int argc, char **argv) { continue; } content_length_buf_size += (size_t)written; - CHECK_ERROR_WRITE(write( + CHECK_ERROR_WRITE_CONTINUE(write( connection_fd, content_length_buf, content_length_buf_size)); - CHECK_ERROR_WRITE(write(connection_fd, "\n", 1)); - CHECK_ERROR_WRITE(write(connection_fd, response, response_size)); + CHECK_ERROR_WRITE_CONTINUE(write(connection_fd, "\n", 1)); + CHECK_ERROR_WRITE_CONTINUE(write( + connection_fd, response, response_size)); free((void*)response); - } else { - const char *response = c_simple_http_response_code_error_to_response( - response_code); - if (response) { - response_size = strlen(response); - CHECK_ERROR_WRITE(write(connection_fd, response, response_size)); + } else if ( + response_code == C_SIMPLE_HTTP_Response_404_Not_Found + && args.static_dir) { + __attribute__((cleanup(c_simple_http_cleanup_static_file_info))) + C_SIMPLE_HTTP_StaticFileInfo file_info = + c_simple_http_get_file(args.static_dir, request_path, 0); + if (file_info.result == STATIC_FILE_RESULT_NoXDGMimeAvailable) { + file_info = c_simple_http_get_file(args.static_dir, request_path, 1); + } + + if (file_info.result != STATIC_FILE_RESULT_OK + || !file_info.buf + || file_info.buf_size == 0 + || !file_info.mime_type) { + if (file_info.result == STATIC_FILE_RESULT_FileError + || file_info.result == STATIC_FILE_RESULT_InternalError) { + response_code = C_SIMPLE_HTTP_Response_500_Internal_Server_Error; + } else if (file_info.result == STATIC_FILE_RESULT_InvalidParameter) { + response_code = C_SIMPLE_HTTP_Response_400_Bad_Request; + } else { + response_code = C_SIMPLE_HTTP_Response_500_Internal_Server_Error; + } + + if (c_simple_http_on_error(response_code, connection_fd)) { + continue; + } } else { - CHECK_ERROR_WRITE(write( - connection_fd, "HTTP/1.1 500 Internal Server Error\n", 35)); - CHECK_ERROR_WRITE(write(connection_fd, "Allow: GET\n", 11)); - CHECK_ERROR_WRITE(write(connection_fd, "Connection: close\n", 18)); - CHECK_ERROR_WRITE(write( - connection_fd, "Content-Type: text/html\n", 24)); - CHECK_ERROR_WRITE(write(connection_fd, "Content-Length: 35\n", 19)); - CHECK_ERROR_WRITE(write( - connection_fd, "\n

500 Internal Server Error

\n", 36)); + CHECK_ERROR_WRITE_CONTINUE(write( + connection_fd, "HTTP/1.1 200 OK\n", 16)); + CHECK_ERROR_WRITE_CONTINUE(write(connection_fd, "Allow: GET\n", 11)); + CHECK_ERROR_WRITE_CONTINUE(write( + connection_fd, "Connection: close\n", 18)); + uint64_t mime_length = strlen(file_info.mime_type); + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *mime_type_buf = malloc(mime_length + 1 + 14 + 1); + snprintf( + mime_type_buf, + mime_length + 1 + 14 + 1, + "Content-Type: %s\n", + file_info.mime_type); + CHECK_ERROR_WRITE_CONTINUE(write( + connection_fd, mime_type_buf, mime_length + 1 + 14)); + uint64_t content_str_len = 0; + for(uint64_t buf_size_temp = file_info.buf_size; + buf_size_temp > 0; + buf_size_temp /= 10) { + ++content_str_len; + } + if (content_str_len == 0) { + content_str_len = 1; + } + __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) + char *content_length_buf = malloc(content_str_len + 1 + 16 + 1); + snprintf( + content_length_buf, + content_str_len + 1 + 16 + 1, + "Content-Length: %lu\n", + file_info.buf_size); + CHECK_ERROR_WRITE_CONTINUE(write( + connection_fd, content_length_buf, content_str_len + 1 + 16)); + CHECK_ERROR_WRITE_CONTINUE(write(connection_fd, "\n", 1)); + CHECK_ERROR_WRITE_CONTINUE(write( + connection_fd, file_info.buf, file_info.buf_size)); + fprintf(stderr, + "NOTICE Found static file for path \"%s\"\n", + request_path); + } + } else { + if (c_simple_http_on_error(response_code, connection_fd)) { + continue; } } close(connection_fd);