diff --git a/src/config.c b/src/config.c index 46e19ed..14e6106 100644 --- a/src/config.c +++ b/src/config.c @@ -36,6 +36,23 @@ typedef struct C_SIMPLE_HTTP_INTERNAL_RequiredCheck { const SDArchiverLinkedList *required; } C_SIMPLE_HTTP_INTERNAL_RequiredCheck; +void c_simple_http_cleanup_config_value( + C_SIMPLE_HTTP_ConfigValue *config_value) { + if (config_value) { + if (config_value->next) { + c_simple_http_cleanup_config_value(config_value->next); + } + if(config_value->value) { + free(config_value->value); + } + free(config_value); + } +} + +void c_simple_http_cleanup_config_value_void_ptr(void *config_value) { + c_simple_http_cleanup_config_value(config_value); +} + int c_simple_http_required_iter_fn(void *data, void *ud) { C_SIMPLE_HTTP_INTERNAL_RequiredIter *req_iter_struct = ud; uint32_t data_str_length = (uint32_t)strlen(data) + 1; @@ -187,21 +204,26 @@ int internal_check_add_value(uint32_t *state, 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) { + C_SIMPLE_HTTP_ConfigValue *config_value = + malloc(sizeof(C_SIMPLE_HTTP_ConfigValue)); + config_value->value = malloc(*value_idx); + config_value->next = NULL; + memcpy(config_value->value, *value_buf, (*value_idx)); + if (simple_archiver_hash_map_insert( + hash_map, + config_value, + key, + separating_key_size, + c_simple_http_cleanup_config_value_void_ptr, + 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); + free(config_value->value); + free(config_value); return 1; } @@ -212,7 +234,7 @@ int internal_check_add_value(uint32_t *state, if (simple_archiver_hash_map_insert( config->hash_map, wrapper, - value, + config_value->value, (*value_idx), c_simple_http_hash_map_wrapper_cleanup_hashmap_fn, simple_archiver_helper_datastructure_cleanup_nop) != 0) { @@ -223,7 +245,7 @@ int internal_check_add_value(uint32_t *state, c_simple_http_hash_map_wrapper_cleanup(wrapper); return 1; } - simple_archiver_list_add(paths, value, + simple_archiver_list_add(paths, config_value->value, simple_archiver_helper_datastructure_cleanup_nop); } else if (!(*current_separating_key_value)) { fprintf( @@ -254,20 +276,36 @@ int internal_check_add_value(uint32_t *state, 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 1; + // Check if key already exists in wrapped hash-map. + C_SIMPLE_HTTP_ConfigValue *config_value = + simple_archiver_hash_map_get(hash_map_wrapper->paths, key, *key_idx); + if (config_value) { + while(config_value->next) { + config_value = config_value->next; + } + config_value->next = malloc(sizeof(C_SIMPLE_HTTP_ConfigValue)); + config_value->next->value = (char*)value; + config_value->next->next = NULL; + } else { + config_value = malloc(sizeof(C_SIMPLE_HTTP_ConfigValue)); + config_value->value = (char*)value; + config_value->next = NULL; + if (simple_archiver_hash_map_insert( + hash_map_wrapper->paths, + config_value, + key, + *key_idx, + c_simple_http_cleanup_config_value_void_ptr, + 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 1; + } } } (*key_idx) = 0; diff --git a/src/config.h b/src/config.h index 9d7c9e6..0857b21 100644 --- a/src/config.h +++ b/src/config.h @@ -30,6 +30,9 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig { /// KEY: "/", VALUE: HashMapWrapper struct /// KEY: "/inner", VALUE: HashMapWrapper struct /// KEY: "/inner/further", VALUE: HashMapWrapper struct + /// + /// Each HashMapWrapper struct's hash-map has the following: + /// KEY: VAR_NAME, VALUE: ConfigValue struct union { SDArchiverHashMap *paths; SDArchiverHashMap *hash_map; @@ -38,6 +41,15 @@ typedef struct C_SIMPLE_HTTP_ParsedConfig { typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HashMapWrapper; +typedef struct C_SIMPLE_HTTP_ConfigValue { + char *value; + struct C_SIMPLE_HTTP_ConfigValue *next; +} C_SIMPLE_HTTP_ConfigValue; + +void c_simple_http_cleanup_config_value( + C_SIMPLE_HTTP_ConfigValue *config_value); +void c_simple_http_cleanup_config_value_void_ptr(void *config_value); + /// Each line in the config should be a key-value pair separated by an equals /// sign "=". All whitespace is ignored unless if the value is "quoted". A part /// of a string can be "quoted" if it is surrounded by three single-quotes or diff --git a/src/http_template.c b/src/http_template.c index b651018..d91c7f0 100644 --- a/src/http_template.c +++ b/src/http_template.c @@ -26,6 +26,7 @@ #include // Local includes. +#include "config.h" #include "helpers.h" /// Returns 0 if "c_string" ends with "_FILE". @@ -73,11 +74,11 @@ char *c_simple_http_path_to_generated( __attribute__((cleanup(simple_archiver_helper_cleanup_c_string))) char *html_buf = NULL; size_t html_buf_size = 0; - const char *html_filename = + C_SIMPLE_HTTP_ConfigValue *html_file_value = simple_archiver_hash_map_get(wrapped_hash_map->hash_map, "HTML_FILE", 10); - if (html_filename) { + if (html_file_value && html_file_value->value) { __attribute__((cleanup(simple_archiver_helper_cleanup_FILE))) - FILE *f = fopen(html_filename, "r"); + FILE *f = fopen(html_file_value->value, "r"); if (!f) { return NULL; } @@ -99,19 +100,19 @@ char *c_simple_http_path_to_generated( html_buf[html_file_size] = 0; html_buf_size = (size_t)html_file_size; if (files_list_out) { - char *html_filename_copy = malloc(strlen(html_filename) + 1); - strcpy(html_filename_copy, html_filename); + char *html_filename_copy = malloc(strlen(html_file_value->value) + 1); + strcpy(html_filename_copy, html_file_value->value); simple_archiver_list_add(*files_list_out, html_filename_copy, NULL); } } else { - char *stored_html = + C_SIMPLE_HTTP_ConfigValue *stored_html_config_value = simple_archiver_hash_map_get(wrapped_hash_map->hash_map, "HTML", 5); - if (!stored_html) { + if (!stored_html_config_value || !stored_html_config_value->value) { return NULL; } - size_t stored_html_size = strlen(stored_html) + 1; + size_t stored_html_size = strlen(stored_html_config_value->value) + 1; html_buf = malloc(stored_html_size); - memcpy(html_buf, stored_html, stored_html_size); + memcpy(html_buf, stored_html_config_value->value, stored_html_size); html_buf_size = stored_html_size - 1; } @@ -177,34 +178,34 @@ char *c_simple_http_path_to_generated( html_buf + last_part->extra, var_size); var[var_size] = 0; - const char *value_c_str = + C_SIMPLE_HTTP_ConfigValue *config_value = simple_archiver_hash_map_get( wrapped_hash_map->hash_map, var, (uint32_t)var_size + 1); - if (value_c_str) { + if (config_value && config_value->value) { if (c_simple_http_internal_ends_with_FILE(var) == 0) { - // Load from file specified by "value_c_str". + // Load from file specified by "config_value->value". __attribute__((cleanup(simple_archiver_helper_cleanup_FILE))) - FILE *f = fopen(value_c_str, "r"); + FILE *f = fopen(config_value->value, "r"); if (!f) { fprintf(stderr, "ERROR Failed to open file \"%s\"!\n", - value_c_str); + config_value->value); return NULL; } else if (fseek(f, 0, SEEK_END) != 0) { fprintf(stderr, "ERROR Failed to seek to end of file \"%s\"!\n", - value_c_str); + config_value->value); return NULL; } long file_size = ftell(f); if (file_size <= 0) { fprintf(stderr, "ERROR Size of file \"%s\" is invalid!\n", - value_c_str); + config_value->value); return NULL; } else if (fseek(f, 0, SEEK_SET) != 0) { fprintf(stderr, "ERROR Failed to seek to start of file " "\"%s\"!\n", - value_c_str); + config_value->value); return NULL; } string_part.size = (size_t)file_size + 1; @@ -217,21 +218,21 @@ char *c_simple_http_path_to_generated( f) != 1) { fprintf(stderr, "ERROR Failed to read from file \"%s\"!\n", - value_c_str); + config_value->value); return NULL; } string_part.buf[string_part.size - 1] = 0; if (files_list_out) { - char *variable_filename = malloc(strlen(value_c_str) + 1); - strcpy(variable_filename, value_c_str); + char *variable_filename = malloc(strlen(config_value->value) + 1); + strcpy(variable_filename, config_value->value); simple_archiver_list_add( *files_list_out, variable_filename, NULL); } } else { - // Variable data is "value_c_str". - string_part.size = strlen(value_c_str) + 1; + // Variable data is "config_value->value". + string_part.size = strlen(config_value->value) + 1; string_part.buf = malloc(string_part.size); - memcpy(string_part.buf, value_c_str, string_part.size); + memcpy(string_part.buf, config_value->value, string_part.size); string_part.buf[string_part.size - 1] = 0; string_part.extra = idx + 1; } diff --git a/src/test.c b/src/test.c index b2382b4..0699574 100644 --- a/src/test.c +++ b/src/test.c @@ -173,46 +173,53 @@ int main(int argc, char **argv) { simple_archiver_hash_map_get(templates.paths, "/", 2); ASSERT_TRUE(first_path_map_wrapper); - const char *value = + C_SIMPLE_HTTP_ConfigValue *value = simple_archiver_hash_map_get(first_path_map_wrapper->paths, "PATH", 5); ASSERT_TRUE(value); - ASSERT_STREQ(value, "/"); + ASSERT_TRUE(value->value); + ASSERT_STREQ(value->value, "/"); value = simple_archiver_hash_map_get(first_path_map_wrapper->paths, "HTML", 5); ASSERT_TRUE(value); + ASSERT_TRUE(value->value); // printf("%s\n", value); - ASSERT_STREQ(value, " one two three "); + ASSERT_STREQ(value->value, " one two three "); value = simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST", 5); ASSERT_TRUE(value); + ASSERT_TRUE(value->value); // printf("%s\n", value); - ASSERT_STREQ(value, " \"one two \"three "); + ASSERT_STREQ(value->value, " \"one two \"three "); value = simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST2", 6); ASSERT_TRUE(value); + ASSERT_TRUE(value->value); // printf("%s\n", value); - ASSERT_STREQ(value, "'\"onetwo\"three''"); + ASSERT_STREQ(value->value, "'\"onetwo\"three''"); value = simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST3", 6); ASSERT_TRUE(value); + ASSERT_TRUE(value->value); // printf("%s\n", value); - ASSERT_STREQ(value, " \"one two \"three ''"); + ASSERT_STREQ(value->value, " \"one two \"three ''"); value = simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST4", 6); ASSERT_TRUE(value); + ASSERT_TRUE(value->value); // printf("%s\n", value); - ASSERT_STREQ(value, " \"\"\"one two \"\"\"three "); + ASSERT_STREQ(value->value, " \"\"\"one two \"\"\"three "); value = simple_archiver_hash_map_get(first_path_map_wrapper->paths, "TEST5", 6); ASSERT_TRUE(value); + ASSERT_TRUE(value->value); // printf("%s\n", value); - ASSERT_STREQ(value, " '''one two '''three "); + ASSERT_STREQ(value->value, " '''one two '''three "); simple_archiver_list_free(&required_names); required_names = simple_archiver_list_init();