Compare commits
2 commits
faa262ba95
...
37e0c3a98b
Author | SHA1 | Date | |
---|---|---|---|
37e0c3a98b | |||
0bbe280e1f |
7 changed files with 225 additions and 154 deletions
|
@ -13,6 +13,7 @@ set(c_simple_http_SOURCES
|
|||
"${CMAKE_CURRENT_SOURCE_DIR}/src/helpers.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/html_cache.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/static.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/generate.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/helpers.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/data_structures/linked_list.c"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/SimpleArchiver/src/data_structures/hash_map.c"
|
||||
|
|
4
Makefile
4
Makefile
|
@ -44,7 +44,8 @@ HEADERS = \
|
|||
src/http_template.h \
|
||||
src/helpers.h \
|
||||
src/html_cache.h \
|
||||
src/static.h
|
||||
src/static.h \
|
||||
src/generate.h
|
||||
|
||||
SOURCES = \
|
||||
src/main.c \
|
||||
|
@ -59,6 +60,7 @@ SOURCES = \
|
|||
src/helpers.c \
|
||||
src/html_cache.c \
|
||||
src/static.c \
|
||||
src/generate.c \
|
||||
third_party/SimpleArchiver/src/helpers.c \
|
||||
third_party/SimpleArchiver/src/data_structures/linked_list.c \
|
||||
third_party/SimpleArchiver/src/data_structures/hash_map.c \
|
||||
|
|
|
@ -126,7 +126,6 @@ void internal_double_quote_decrement(uint_fast8_t *double_quote_count,
|
|||
/// Returns non-zero if config should be returned.
|
||||
int internal_check_add_value(uint32_t *state,
|
||||
char **key_buf,
|
||||
uint32_t *key_capacity,
|
||||
uint32_t *key_idx,
|
||||
char **value_buf,
|
||||
uint32_t *value_capacity,
|
||||
|
@ -496,7 +495,6 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
|||
} else {
|
||||
if (internal_check_add_value(&state,
|
||||
&key_buf,
|
||||
&key_capacity,
|
||||
&key_idx,
|
||||
&value_buf,
|
||||
&value_capacity,
|
||||
|
@ -520,7 +518,6 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
|||
|
||||
if (internal_check_add_value(&state,
|
||||
&key_buf,
|
||||
&key_capacity,
|
||||
&key_idx,
|
||||
&value_buf,
|
||||
&value_capacity,
|
||||
|
|
175
src/generate.c
Normal file
175
src/generate.c
Normal file
|
@ -0,0 +1,175 @@
|
|||
// ISC License
|
||||
//
|
||||
// Copyright (c) 2024 Stephen Seo
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#include "generate.h"
|
||||
|
||||
// Standard library includes.
|
||||
#include <string.h>
|
||||
|
||||
// Linux/Unix includes.
|
||||
#include <libgen.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Local includes.
|
||||
#include "helpers.h"
|
||||
#include "http_template.h"
|
||||
|
||||
// Third party includes.
|
||||
#include <SimpleArchiver/src/helpers.h>
|
||||
#include <SimpleArchiver/src/data_structures/hash_map.h>
|
||||
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
||||
|
||||
int c_simple_http_generate_paths_fn(const void *key,
|
||||
size_t key_size,
|
||||
__attribute__((unused)) const void *value,
|
||||
void *ud) {
|
||||
const char *path = key;
|
||||
const ConnectionContext *ctx = ud;
|
||||
const char *generate_dir = ctx->args->generate_dir;
|
||||
|
||||
const unsigned long path_len = key_size - 1;
|
||||
const unsigned long generate_dir_len = strlen(generate_dir);
|
||||
|
||||
__attribute__((cleanup(simple_archiver_list_free)))
|
||||
SDArchiverLinkedList *string_parts = simple_archiver_list_init();
|
||||
|
||||
// Add generate_dir as first path of paths to join.
|
||||
c_simple_http_add_string_part(string_parts, generate_dir, 0);
|
||||
|
||||
// Ensure next character after generate_dir contains a '/' if generate_dir
|
||||
// didn't contain one at the end.
|
||||
if (generate_dir_len > 0 && generate_dir[generate_dir_len - 1] != '/') {
|
||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
||||
}
|
||||
|
||||
// Append the path.
|
||||
if (strcmp(path, "/") != 0) {
|
||||
// Is not root.
|
||||
uint32_t idx = 0;
|
||||
while (idx <= path_len && path[idx] == '/') {
|
||||
++idx;
|
||||
}
|
||||
c_simple_http_add_string_part(string_parts, path + idx, 0);
|
||||
}
|
||||
|
||||
// Add the final '/'.
|
||||
if (path_len > 0 && path[path_len - 1] != '/') {
|
||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
||||
}
|
||||
|
||||
// Add the ending "index.html".
|
||||
c_simple_http_add_string_part(string_parts, "index.html", 0);
|
||||
|
||||
// Get the combined string.
|
||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||
char *generated_path = c_simple_http_combine_string_parts(string_parts);
|
||||
if (!generated_path) {
|
||||
fprintf(stderr, "ERROR Failed to get generated path (path: %s)!\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((ctx->args->flags & 4) == 0) {
|
||||
// Overwrite not enabled, check if file already exists.
|
||||
FILE *fd = fopen(generated_path, "rb");
|
||||
if (fd) {
|
||||
fclose(fd);
|
||||
fprintf(
|
||||
stderr,
|
||||
"WARNING Path \"%s\" exists and \"--generate-enable-overwrite\" not "
|
||||
"specified, skipping!\n",
|
||||
generated_path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the required dirs exist.
|
||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||
char *generated_path_dup = strdup(generated_path);
|
||||
|
||||
uint_fast8_t did_make_generated_path_dir = 0;
|
||||
char *generated_path_dir = dirname(generated_path_dup);
|
||||
if (generated_path_dir) {
|
||||
DIR *fd = opendir(generated_path_dir);
|
||||
if (!fd) {
|
||||
if (errno == ENOENT) {
|
||||
c_simple_http_helper_mkdir_tree(generated_path_dir);
|
||||
did_make_generated_path_dir = 1;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"ERROR opendir on path dirname failed unexpectedly (path: %s)!"
|
||||
"\n",
|
||||
path);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
// Directory already exists.
|
||||
closedir(fd);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"ERROR Failed to get dirname of generated path dir (path: %s)"
|
||||
"!\n",
|
||||
path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Generate the html.
|
||||
size_t html_buf_size = 0;
|
||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||
char *html_buf = c_simple_http_path_to_generated(path,
|
||||
ctx->parsed,
|
||||
&html_buf_size,
|
||||
NULL);
|
||||
if (!html_buf || html_buf_size == 0) {
|
||||
fprintf(stderr,
|
||||
"WARNING Failed to generate html for generate (path: %s), "
|
||||
"skipping!\n",
|
||||
path);
|
||||
if (did_make_generated_path_dir) {
|
||||
if (rmdir(generated_path_dir) == -1) {
|
||||
fprintf(stderr,
|
||||
"WARNING rmdir on generated_path_dir failed, errno: %d\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Save the html.
|
||||
FILE *fd = fopen(generated_path, "wb");
|
||||
if (!fd) {
|
||||
fprintf(stderr,
|
||||
"WARNING Failed to open \"%s\" for writing, skipping!\n",
|
||||
generated_path);
|
||||
return 0;
|
||||
}
|
||||
unsigned long fwrite_ret = fwrite(html_buf, 1, html_buf_size, fd);
|
||||
if (fwrite_ret < html_buf_size) {
|
||||
fclose(fd);
|
||||
unlink(generated_path);
|
||||
fprintf(stderr,
|
||||
"ERROR Unable to write entirely to \"%s\"!\n",
|
||||
generated_path);
|
||||
return 1;
|
||||
} else {
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
30
src/generate.h
Normal file
30
src/generate.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
// ISC License
|
||||
//
|
||||
// Copyright (c) 2024 Stephen Seo
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
#ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_GENERATE_H_
|
||||
#define SEODISPARATE_COM_C_SIMPLE_HTTP_GENERATE_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/// See this function's usage in main.c.
|
||||
int c_simple_http_generate_paths_fn(const void *key,
|
||||
size_t key_size,
|
||||
const void *value,
|
||||
void *ud);
|
||||
|
||||
#endif
|
||||
|
||||
// vim: et ts=2 sts=2 sw=2
|
|
@ -21,9 +21,23 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// libc includes.
|
||||
#include <time.h>
|
||||
|
||||
// Local includes.
|
||||
#include "config.h"
|
||||
#include "arg_parse.h"
|
||||
|
||||
// Third-party includes.
|
||||
#include <SimpleArchiver/src/data_structures/linked_list.h>
|
||||
|
||||
typedef struct ConnectionContext {
|
||||
char *buf;
|
||||
const Args *args;
|
||||
C_SIMPLE_HTTP_ParsedConfig *parsed;
|
||||
struct timespec current_time;
|
||||
} ConnectionContext;
|
||||
|
||||
typedef struct C_SIMPLE_HTTP_String_Part {
|
||||
char *buf;
|
||||
size_t size;
|
||||
|
|
152
src/main.c
152
src/main.c
|
@ -21,10 +21,7 @@
|
|||
#include <stdint.h>
|
||||
|
||||
// Linux/Unix includes.
|
||||
#include <libgen.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
@ -46,6 +43,7 @@
|
|||
#include "http_template.h"
|
||||
#include "tcp_socket.h"
|
||||
#include "signal_handling.h"
|
||||
#include "generate.h"
|
||||
#include "globals.h"
|
||||
#include "constants.h"
|
||||
#include "http.h"
|
||||
|
@ -80,13 +78,6 @@ typedef struct ConnectionItem {
|
|||
struct in6_addr peer_addr;
|
||||
} ConnectionItem;
|
||||
|
||||
typedef struct ConnectionContext {
|
||||
char *buf;
|
||||
const Args *args;
|
||||
C_SIMPLE_HTTP_ParsedConfig *parsed;
|
||||
struct timespec current_time;
|
||||
} ConnectionContext;
|
||||
|
||||
void c_simple_http_cleanup_connection_item(void *data) {
|
||||
ConnectionItem *citem = data;
|
||||
if (citem) {
|
||||
|
@ -332,145 +323,6 @@ int c_simple_http_manage_connections(void *data, void *ud) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int generate_paths_fn(const void *key,
|
||||
size_t key_size,
|
||||
const void *value,
|
||||
void *ud) {
|
||||
const char *path = key;
|
||||
const ConnectionContext *ctx = ud;
|
||||
const char *generate_dir = ctx->args->generate_dir;
|
||||
|
||||
const unsigned long path_len = strlen(path);
|
||||
const unsigned long generate_dir_len = strlen(generate_dir);
|
||||
|
||||
__attribute__((cleanup(simple_archiver_list_free)))
|
||||
SDArchiverLinkedList *string_parts = simple_archiver_list_init();
|
||||
|
||||
// Add generate_dir as first path of paths to join.
|
||||
c_simple_http_add_string_part(string_parts, generate_dir, 0);
|
||||
|
||||
// Ensure next character after generate_dir contains a '/' if generate_dir
|
||||
// didn't contain one at the end.
|
||||
if (generate_dir_len > 0 && generate_dir[generate_dir_len - 1] != '/') {
|
||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
||||
}
|
||||
|
||||
// Append the path.
|
||||
if (strcmp(path, "/") != 0) {
|
||||
// Is not root.
|
||||
uint32_t idx = 0;
|
||||
while (idx <= path_len && path[idx] == '/') {
|
||||
++idx;
|
||||
}
|
||||
c_simple_http_add_string_part(string_parts, path + idx, 0);
|
||||
}
|
||||
|
||||
// Add the final '/'.
|
||||
if (path_len > 0 && path[path_len - 1] != '/') {
|
||||
c_simple_http_add_string_part(string_parts, "/", 0);
|
||||
}
|
||||
|
||||
// Add the ending "index.html".
|
||||
c_simple_http_add_string_part(string_parts, "index.html", 0);
|
||||
|
||||
// Get the combined string.
|
||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||
char *generated_path = c_simple_http_combine_string_parts(string_parts);
|
||||
if (!generated_path) {
|
||||
fprintf(stderr, "ERROR Failed to get generated path (path: %s)!\n", path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((ctx->args->flags & 4) == 0) {
|
||||
// Overwrite not enabled, check if file already exists.
|
||||
FILE *fd = fopen(generated_path, "rb");
|
||||
if (fd) {
|
||||
fclose(fd);
|
||||
fprintf(
|
||||
stderr,
|
||||
"WARNING Path \"%s\" exists and \"--generate-enable-overwrite\" not "
|
||||
"specified, skipping!\n",
|
||||
generated_path);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the required dirs exist.
|
||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||
char *generated_path_dup = strdup(generated_path);
|
||||
|
||||
uint_fast8_t did_make_generated_path_dir = 0;
|
||||
char *generated_path_dir = dirname(generated_path_dup);
|
||||
if (generated_path_dir) {
|
||||
DIR *fd = opendir(generated_path_dir);
|
||||
if (!fd) {
|
||||
if (errno == ENOENT) {
|
||||
c_simple_http_helper_mkdir_tree(generated_path_dir);
|
||||
did_make_generated_path_dir = 1;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"ERROR opendir on path dirname failed unexpectedly (path: %s)!"
|
||||
"\n",
|
||||
path);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
// Directory already exists.
|
||||
closedir(fd);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"ERROR Failed to get dirname of generated path dir (path: %s)"
|
||||
"!\n",
|
||||
path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Generate the html.
|
||||
size_t html_buf_size = 0;
|
||||
__attribute__((cleanup(simple_archiver_helper_cleanup_c_string)))
|
||||
char *html_buf = c_simple_http_path_to_generated(path,
|
||||
ctx->parsed,
|
||||
&html_buf_size,
|
||||
NULL);
|
||||
if (!html_buf || html_buf_size == 0) {
|
||||
fprintf(stderr,
|
||||
"WARNING Failed to generate html for generate (path: %s), "
|
||||
"skipping!\n",
|
||||
path);
|
||||
if (did_make_generated_path_dir) {
|
||||
if (rmdir(generated_path_dir) == -1) {
|
||||
fprintf(stderr,
|
||||
"WARNING rmdir on generated_path_dir failed, errno: %d\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Save the html.
|
||||
FILE *fd = fopen(generated_path, "wb");
|
||||
if (!fd) {
|
||||
fprintf(stderr,
|
||||
"WARNING Failed to open \"%s\" for writing, skipping!\n",
|
||||
generated_path);
|
||||
return 0;
|
||||
}
|
||||
unsigned long fwrite_ret = fwrite(html_buf, 1, html_buf_size, fd);
|
||||
if (fwrite_ret < html_buf_size) {
|
||||
fclose(fd);
|
||||
unlink(generated_path);
|
||||
fprintf(stderr,
|
||||
"ERROR Unable to write entirely to \"%s\"!\n",
|
||||
generated_path);
|
||||
return 1;
|
||||
} else {
|
||||
fclose(fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
__attribute__((cleanup(c_simple_http_free_args)))
|
||||
Args args = parse_args(argc, argv);
|
||||
|
@ -500,7 +352,7 @@ int main(int argc, char **argv) {
|
|||
ctx.args = &args;
|
||||
ctx.parsed = &parsed_config;
|
||||
if (simple_archiver_hash_map_iter(parsed_config.paths,
|
||||
generate_paths_fn,
|
||||
c_simple_http_generate_paths_fn,
|
||||
&ctx)) {
|
||||
fprintf(stderr, "ERROR during generating!\n");
|
||||
return 1;
|
||||
|
|
Loading…
Reference in a new issue