Compare commits
2 commits
1d5fb6bbbd
...
e458c6e87b
Author | SHA1 | Date | |
---|---|---|---|
e458c6e87b | |||
2d96295555 |
3 changed files with 212 additions and 180 deletions
323
src/config.c
323
src/config.c
|
@ -76,6 +76,145 @@
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHECK_ADD_VALUE() \
|
||||||
|
if (value_idx < C_SIMPLE_HTTP_CONFIG_BUF_SIZE) { \
|
||||||
|
value_buf[value_idx++] = 0; \
|
||||||
|
} else { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"ERROR: config file \"value\" is larger than %u bytes!\n", \
|
||||||
|
C_SIMPLE_HTTP_CONFIG_BUF_SIZE - 1); \
|
||||||
|
c_simple_http_clean_up_parsed_config(&config); \
|
||||||
|
config.hash_map = NULL; \
|
||||||
|
return config; \
|
||||||
|
} \
|
||||||
|
state &= 0xFFFFFFFE; \
|
||||||
|
\
|
||||||
|
/* Check if key is separating_key. */ \
|
||||||
|
if (strcmp((char*)key_buf, separating_key) == 0) { \
|
||||||
|
if (current_separating_key_value) { \
|
||||||
|
if (required_names) { \
|
||||||
|
C_SIMPLE_HTTP_HashMapWrapper *hash_map_wrapper = \
|
||||||
|
simple_archiver_hash_map_get( \
|
||||||
|
config.hash_map, \
|
||||||
|
current_separating_key_value, \
|
||||||
|
current_separating_key_value_size); \
|
||||||
|
C_SIMPLE_HTTP_INTERNAL_RequiredIter req_iter_struct; \
|
||||||
|
req_iter_struct.hash_map = hash_map_wrapper->hash_map; \
|
||||||
|
if (paths->count != 0) { \
|
||||||
|
req_iter_struct.path = paths->tail->prev->data; \
|
||||||
|
} else { \
|
||||||
|
req_iter_struct.path = NULL; \
|
||||||
|
} \
|
||||||
|
const char *missing_key = simple_archiver_list_get( \
|
||||||
|
required_names, \
|
||||||
|
c_simple_http_required_iter_fn, \
|
||||||
|
&req_iter_struct); \
|
||||||
|
if (missing_key) { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"WARNING: config file did not have required key \"%s\"!" \
|
||||||
|
" Returning NULL map!\n", \
|
||||||
|
missing_key); \
|
||||||
|
c_simple_http_clean_up_parsed_config(&config); \
|
||||||
|
config.hash_map = NULL; \
|
||||||
|
return config; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
state &= 0xFFFFFFFD; \
|
||||||
|
free(current_separating_key_value); \
|
||||||
|
} \
|
||||||
|
current_separating_key_value = malloc(value_idx); \
|
||||||
|
memcpy(current_separating_key_value, value_buf, value_idx); \
|
||||||
|
current_separating_key_value_size = value_idx; \
|
||||||
|
/* At this point, key is separating_key. */ \
|
||||||
|
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init(); \
|
||||||
|
unsigned char *key = malloc(separating_key_size); \
|
||||||
|
strncpy((char*)key, separating_key, separating_key_size); \
|
||||||
|
unsigned char *value = malloc(value_idx); \
|
||||||
|
memcpy(value, value_buf, value_idx); \
|
||||||
|
if (simple_archiver_hash_map_insert(&hash_map, \
|
||||||
|
value, \
|
||||||
|
key, \
|
||||||
|
separating_key_size, \
|
||||||
|
NULL, \
|
||||||
|
NULL) != 0) { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"ERROR: Failed to create hash map for new separating_key " \
|
||||||
|
"block!\n"); \
|
||||||
|
c_simple_http_clean_up_parsed_config(&config); \
|
||||||
|
config.hash_map = NULL; \
|
||||||
|
free(key); \
|
||||||
|
free(value); \
|
||||||
|
return config; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
C_SIMPLE_HTTP_HashMapWrapper *wrapper = malloc(sizeof(C_SIMPLE_HTTP_HashMapWrapper)); \
|
||||||
|
wrapper->paths = hash_map; \
|
||||||
|
\
|
||||||
|
if (simple_archiver_hash_map_insert( \
|
||||||
|
&config.hash_map, \
|
||||||
|
wrapper, \
|
||||||
|
value, \
|
||||||
|
value_idx, \
|
||||||
|
c_simple_http_hash_map_wrapper_cleanup_hashmap_fn, \
|
||||||
|
simple_archiver_helper_datastructure_cleanup_nop) != 0) { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"ERROR: Failed to insert new hash map for new PATH block!\n"); \
|
||||||
|
c_simple_http_clean_up_parsed_config(&config); \
|
||||||
|
config.hash_map = NULL; \
|
||||||
|
c_simple_http_hash_map_wrapper_cleanup(wrapper); \
|
||||||
|
return config; \
|
||||||
|
} \
|
||||||
|
simple_archiver_list_add(paths, value, \
|
||||||
|
simple_archiver_helper_datastructure_cleanup_nop); \
|
||||||
|
} else if (!current_separating_key_value) { \
|
||||||
|
fprintf( \
|
||||||
|
stderr, \
|
||||||
|
"ERROR: config file has invalid key: No preceding \"%s\" " \
|
||||||
|
"key!\n", separating_key); \
|
||||||
|
c_simple_http_clean_up_parsed_config(&config); \
|
||||||
|
config.hash_map = NULL; \
|
||||||
|
return config; \
|
||||||
|
} else { \
|
||||||
|
/* Non-separating_key key. */ \
|
||||||
|
C_SIMPLE_HTTP_HashMapWrapper *hash_map_wrapper = \
|
||||||
|
simple_archiver_hash_map_get( \
|
||||||
|
config.hash_map, \
|
||||||
|
current_separating_key_value, \
|
||||||
|
current_separating_key_value_size); \
|
||||||
|
if (!hash_map_wrapper) { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"ERROR: Internal error failed to get existing hash map with path " \
|
||||||
|
"\"%s\"!", current_separating_key_value); \
|
||||||
|
c_simple_http_clean_up_parsed_config(&config); \
|
||||||
|
config.hash_map = NULL; \
|
||||||
|
return config; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
unsigned char *key = malloc(key_idx); \
|
||||||
|
memcpy(key, key_buf, key_idx); \
|
||||||
|
unsigned char *value = malloc(value_idx); \
|
||||||
|
memcpy(value, value_buf, value_idx); \
|
||||||
|
\
|
||||||
|
if (simple_archiver_hash_map_insert(&hash_map_wrapper->paths, \
|
||||||
|
value, \
|
||||||
|
key, \
|
||||||
|
key_idx, \
|
||||||
|
NULL, \
|
||||||
|
NULL) != 0) { \
|
||||||
|
fprintf(stderr, \
|
||||||
|
"ERROR: Internal error failed to insert into hash map with path " \
|
||||||
|
"\"%s\"!", current_separating_key_value); \
|
||||||
|
c_simple_http_clean_up_parsed_config(&config); \
|
||||||
|
config.hash_map = NULL; \
|
||||||
|
free(key); \
|
||||||
|
free(value); \
|
||||||
|
return config; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
key_idx = 0; \
|
||||||
|
value_idx = 0;
|
||||||
|
|
||||||
void c_simple_http_hash_map_wrapper_cleanup_hashmap_fn(void *data) {
|
void c_simple_http_hash_map_wrapper_cleanup_hashmap_fn(void *data) {
|
||||||
C_SIMPLE_HTTP_HashMapWrapper *wrapper = data;
|
C_SIMPLE_HTTP_HashMapWrapper *wrapper = data;
|
||||||
simple_archiver_hash_map_free(&wrapper->paths);
|
simple_archiver_hash_map_free(&wrapper->paths);
|
||||||
|
@ -279,188 +418,18 @@ C_SIMPLE_HTTP_ParsedConfig c_simple_http_parse_config(
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (value_idx < C_SIMPLE_HTTP_CONFIG_BUF_SIZE) {
|
CHECK_ADD_VALUE()
|
||||||
value_buf[value_idx++] = 0;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR: config file \"value\" is larger than %u bytes!\n",
|
|
||||||
C_SIMPLE_HTTP_CONFIG_BUF_SIZE - 1);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
state &= 0xFFFFFFFE;
|
|
||||||
|
|
||||||
// Check if key is separating_key.
|
|
||||||
if (strcmp((char*)key_buf, separating_key) == 0) {
|
|
||||||
if (current_separating_key_value) {
|
|
||||||
if (required_names) {
|
|
||||||
C_SIMPLE_HTTP_HashMapWrapper *hash_map_wrapper =
|
|
||||||
simple_archiver_hash_map_get(
|
|
||||||
config.hash_map,
|
|
||||||
current_separating_key_value,
|
|
||||||
current_separating_key_value_size);
|
|
||||||
C_SIMPLE_HTTP_INTERNAL_RequiredIter req_iter_struct;
|
|
||||||
req_iter_struct.hash_map = hash_map_wrapper->hash_map;
|
|
||||||
if (paths->count != 0) {
|
|
||||||
req_iter_struct.path = paths->tail->prev->data;
|
|
||||||
} else {
|
|
||||||
req_iter_struct.path = NULL;
|
|
||||||
}
|
|
||||||
const char *missing_key = simple_archiver_list_get(
|
|
||||||
required_names,
|
|
||||||
c_simple_http_required_iter_fn,
|
|
||||||
&req_iter_struct);
|
|
||||||
if (missing_key) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"WARNING: config file did not have required key \"%s\"!"
|
|
||||||
" Returning NULL map!\n",
|
|
||||||
missing_key);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state &= 0xFFFFFFFD;
|
|
||||||
free(current_separating_key_value);
|
|
||||||
}
|
|
||||||
current_separating_key_value = malloc(value_idx);
|
|
||||||
memcpy(current_separating_key_value, value_buf, value_idx);
|
|
||||||
current_separating_key_value_size = value_idx;
|
|
||||||
// At this point, key is separating_key.
|
|
||||||
SDArchiverHashMap *hash_map = simple_archiver_hash_map_init();
|
|
||||||
unsigned char *key = malloc(separating_key_size);
|
|
||||||
strncpy((char*)key, separating_key, separating_key_size);
|
|
||||||
unsigned char *value = malloc(value_idx);
|
|
||||||
memcpy(value, value_buf, value_idx);
|
|
||||||
if (simple_archiver_hash_map_insert(&hash_map,
|
|
||||||
value,
|
|
||||||
key,
|
|
||||||
separating_key_size,
|
|
||||||
NULL,
|
|
||||||
NULL) != 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR: Failed to create hash map for new separating_key "
|
|
||||||
"block!\n");
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
free(key);
|
|
||||||
free(value);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
C_SIMPLE_HTTP_HashMapWrapper *wrapper = malloc(sizeof(C_SIMPLE_HTTP_HashMapWrapper));
|
|
||||||
wrapper->paths = hash_map;
|
|
||||||
|
|
||||||
if (simple_archiver_hash_map_insert(
|
|
||||||
&config.hash_map,
|
|
||||||
wrapper,
|
|
||||||
value,
|
|
||||||
value_idx,
|
|
||||||
c_simple_http_hash_map_wrapper_cleanup_hashmap_fn,
|
|
||||||
simple_archiver_helper_datastructure_cleanup_nop) != 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR: Failed to insert new hash map for new PATH block!\n");
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
c_simple_http_hash_map_wrapper_cleanup(wrapper);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
simple_archiver_list_add(paths, value,
|
|
||||||
simple_archiver_helper_datastructure_cleanup_nop);
|
|
||||||
} else if (!current_separating_key_value) {
|
|
||||||
fprintf(
|
|
||||||
stderr,
|
|
||||||
"ERROR: config file has invalid key: No preceding \"%s\" "
|
|
||||||
"key!\n", separating_key);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
} else {
|
|
||||||
// Non-separating_key key.
|
|
||||||
C_SIMPLE_HTTP_HashMapWrapper *hash_map_wrapper =
|
|
||||||
simple_archiver_hash_map_get(
|
|
||||||
config.hash_map,
|
|
||||||
current_separating_key_value,
|
|
||||||
current_separating_key_value_size);
|
|
||||||
if (!hash_map_wrapper) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR: Internal error failed to get existing hash map with path "
|
|
||||||
"\"%s\"!", current_separating_key_value);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char *key = malloc(key_idx);
|
|
||||||
memcpy(key, key_buf, key_idx);
|
|
||||||
unsigned char *value;
|
|
||||||
if (strcmp((char*)key_buf, "HTML_FILE") == 0) {
|
|
||||||
__attribute__((cleanup(simple_archiver_helper_cleanup_FILE)))
|
|
||||||
FILE *html_file = fopen((char*)value_buf, "r");
|
|
||||||
if (!html_file) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR: Internal error failed to open HTML_FILE \"%s\"!",
|
|
||||||
value_buf);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(html_file, 0, SEEK_END);
|
|
||||||
long file_size = ftell(html_file);
|
|
||||||
if (file_size <= 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR: Internal error HTML_FILE \"%s\" is invalid size!",
|
|
||||||
value_buf);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
fseek(html_file, 0, SEEK_SET);
|
|
||||||
unsigned long file_size_u = file_size;
|
|
||||||
|
|
||||||
unsigned char *read_buf = malloc(file_size_u);
|
|
||||||
size_t read_amount = 0;
|
|
||||||
read_amount = fread(read_buf, 1, file_size_u, html_file);
|
|
||||||
if (read_amount != file_size_u) {
|
|
||||||
fprintf(stderr, "ERROR: Failed to read HTML_FILE \"%s\"!\n",
|
|
||||||
value_buf);
|
|
||||||
free(read_buf);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
value = read_buf;
|
|
||||||
} else {
|
|
||||||
value = malloc(value_idx);
|
|
||||||
memcpy(value, value_buf, value_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (simple_archiver_hash_map_insert(&hash_map_wrapper->paths,
|
|
||||||
value,
|
|
||||||
key,
|
|
||||||
key_idx,
|
|
||||||
NULL,
|
|
||||||
NULL) != 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"ERROR: Internal error failed to insert into hash map with path "
|
|
||||||
"\"%s\"!", current_separating_key_value);
|
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
|
||||||
config.hash_map = NULL;
|
|
||||||
free(key);
|
|
||||||
free(value);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
key_idx = 0;
|
|
||||||
value_idx = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
simple_archiver_helper_cleanup_FILE(&f);
|
simple_archiver_helper_cleanup_FILE(&f);
|
||||||
|
|
||||||
|
if ((state & 0x1) == 1 && (state & 0xC) == 0 && value_idx != 0) {
|
||||||
|
// Leftover "value" not added yet.
|
||||||
|
|
||||||
|
CHECK_ADD_VALUE()
|
||||||
|
}
|
||||||
|
|
||||||
if (!current_separating_key_value) {
|
if (!current_separating_key_value) {
|
||||||
fprintf(stderr, "ERROR: Never got \"PATH\" key in config!\n");
|
fprintf(stderr, "ERROR: Never got \"PATH\" key in config!\n");
|
||||||
c_simple_http_clean_up_parsed_config(&config);
|
c_simple_http_clean_up_parsed_config(&config);
|
||||||
|
|
|
@ -248,7 +248,7 @@ char *c_simple_http_path_to_generated(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
C_SIMPLE_HTTP_INTERNAL_Template_Node to_fill;
|
C_SIMPLE_HTTP_INTERNAL_Template_Node to_fill;
|
||||||
to_fill.html = malloc(final_size);
|
to_fill.html = malloc(final_size + 1);
|
||||||
to_fill.html_size = 0;
|
to_fill.html_size = 0;
|
||||||
to_fill.html_capacity = final_size;
|
to_fill.html_capacity = final_size;
|
||||||
if (simple_archiver_list_get(
|
if (simple_archiver_list_get(
|
||||||
|
@ -259,6 +259,7 @@ char *c_simple_http_path_to_generated(
|
||||||
free(to_fill.html);
|
free(to_fill.html);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
to_fill.html[final_size] = 0;
|
||||||
return to_fill.html;
|
return to_fill.html;
|
||||||
} else {
|
} else {
|
||||||
// Prevent cleanup fn from "free"ing html_buf and return it verbatim.
|
// Prevent cleanup fn from "free"ing html_buf and return it verbatim.
|
||||||
|
|
66
src/test.c
66
src/test.c
|
@ -120,9 +120,11 @@ int main(void) {
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
fwrite("TEST3=something\n", 1, 16, test_file)
|
fwrite("TEST3=something\n", 1, 16, test_file)
|
||||||
== 16);
|
== 16);
|
||||||
|
// No endline at the end of file to check for case where the config file
|
||||||
|
// has no endline.
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
fwrite("TEST2=' \"one two \"three ''\n", 1, 27, test_file)
|
fwrite("TEST2=' \"one two \"three ''", 1, 26, test_file)
|
||||||
== 27);
|
== 26);
|
||||||
simple_archiver_helper_cleanup_FILE(&test_file);
|
simple_archiver_helper_cleanup_FILE(&test_file);
|
||||||
|
|
||||||
__attribute__((cleanup(simple_archiver_list_free)))
|
__attribute__((cleanup(simple_archiver_list_free)))
|
||||||
|
@ -279,6 +281,66 @@ int main(void) {
|
||||||
"<h1> Some text. </h1><br><h2> More text. </h2>")
|
"<h1> Some text. </h1><br><h2> More text. </h2>")
|
||||||
== 0);
|
== 0);
|
||||||
simple_archiver_helper_cleanup_c_string(&buf);
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
|
|
||||||
|
const char *test_http_template_filename3 =
|
||||||
|
"/tmp/c_simple_http_template_test3.config";
|
||||||
|
const char *test_http_template_html_filename =
|
||||||
|
"/tmp/c_simple_http_template_test.html";
|
||||||
|
test_file = fopen(test_http_template_filename3, "w");
|
||||||
|
ASSERT_TRUE(test_file);
|
||||||
|
|
||||||
|
ASSERT_TRUE(
|
||||||
|
fwrite(
|
||||||
|
"PATH=/\nHTML_FILE=/tmp/c_simple_http_template_test.html\n",
|
||||||
|
1,
|
||||||
|
55,
|
||||||
|
test_file)
|
||||||
|
== 55);
|
||||||
|
ASSERT_TRUE(
|
||||||
|
fwrite(
|
||||||
|
"testVar=''' testVar text. '''\ntestVar2=''' testVar2 text. '''\n",
|
||||||
|
1,
|
||||||
|
62,
|
||||||
|
test_file)
|
||||||
|
== 62);
|
||||||
|
simple_archiver_helper_cleanup_FILE(&test_file);
|
||||||
|
|
||||||
|
test_file = fopen(test_http_template_html_filename, "w");
|
||||||
|
ASSERT_TRUE(test_file);
|
||||||
|
|
||||||
|
ASSERT_TRUE(
|
||||||
|
fwrite(
|
||||||
|
"<h1>{{{testVar}}}</h1><br><h2>{{{testVar2}}}</h2>",
|
||||||
|
1,
|
||||||
|
49,
|
||||||
|
test_file)
|
||||||
|
== 49);
|
||||||
|
simple_archiver_helper_cleanup_FILE(&test_file);
|
||||||
|
|
||||||
|
simple_archiver_list_free(&required_names);
|
||||||
|
required_names = simple_archiver_list_init();
|
||||||
|
simple_archiver_list_add(
|
||||||
|
required_names,
|
||||||
|
"HTML_FILE",
|
||||||
|
simple_archiver_helper_datastructure_cleanup_nop);
|
||||||
|
|
||||||
|
c_simple_http_clean_up_parsed_config(&config);
|
||||||
|
config = c_simple_http_parse_config(
|
||||||
|
test_http_template_filename3,
|
||||||
|
"PATH",
|
||||||
|
required_names
|
||||||
|
);
|
||||||
|
ASSERT_TRUE(config.paths != NULL);
|
||||||
|
|
||||||
|
buf = c_simple_http_path_to_generated("/", &config);
|
||||||
|
ASSERT_TRUE(buf != NULL);
|
||||||
|
printf("%s\n", buf);
|
||||||
|
ASSERT_TRUE(
|
||||||
|
strcmp(
|
||||||
|
buf,
|
||||||
|
"<h1> testVar text. </h1><br><h2> testVar2 text. </h2>")
|
||||||
|
== 0);
|
||||||
|
simple_archiver_helper_cleanup_c_string(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN()
|
RETURN()
|
||||||
|
|
Loading…
Reference in a new issue