From 8726f502616bea28beb643e85ce22f7923221dbc Mon Sep 17 00:00:00 2001 From: Pradana Aumars Date: Sat, 12 Jun 2021 11:06:21 +0200 Subject: [PATCH] Failed attempt to fix XML parsing: parsing should be done block by block in separate functions to facilitate unit testing --- src/calibrate.c | 166 +++++++++++++++++++++++++++++++++------- src/calibrate.h | 2 + tests/check_calibrate.c | 48 ++++++++++-- 3 files changed, 182 insertions(+), 34 deletions(-) diff --git a/src/calibrate.c b/src/calibrate.c index df34a07..ad36405 100644 --- a/src/calibrate.c +++ b/src/calibrate.c @@ -11,7 +11,9 @@ #define BUFFER_SIZE 1000 -static const char* paths_xml = "/.local/modetw/paths.xml"; +// For testing only +static const char* paths_xml = "../paths.xml"; +static const char* conf = "../modetw.conf"; /** * Convert the text encoding of a string from UTF8 to chosen encoding. @@ -104,9 +106,7 @@ replace_text_encoded(const char *file, const char *before, const char *after, ex /* fopen() return NULL if unable to open file in given mode. */ if (fPtr == NULL || fTemp == NULL) { - /* Unable to open file hence exit */ - printf("\nUnable to open file.\n"); - printf("Please check whether file exists and you have read/write privilege.\n"); + e->type = NO_FILE; return 1; } @@ -135,6 +135,7 @@ replace_text_encoded(const char *file, const char *before, const char *after, ex /* Rename temp file as original file */ rename("replace.tmp", file); + remove("replace.tmp"); return 0; } @@ -155,51 +156,160 @@ int calibrate(exception_t *e) return 0; } +static int +parse_file(xmlNode *cur, char* type, exception_t *e) { + file_t *f; + xmlChar *name, *sum; + char abspath[CHAR_MAX]; + + cur = cur->children; + while (cur != NULL) + { + if (xmlStrEqual(cur->name, (const xmlChar*) "name")) + { + name = xmlNodeGetContent(cur->children); + break; + } + cur = cur->next; + } + + sprintf(abspath, "%s/%s", type, name); + + while (cur != NULL) + { + if (xmlStrEqual(cur->name, (const xmlChar*) "sum")) + { + sum = xmlNodeGetContent(cur->children); + break; + } + cur = cur->next; + } + + f = file_init((char*) abspath, FILEPATH_ABSOLUTE, e); + file_md5_gen(f, e); + file_md5_str(f, e); + if (!strcmp(f->hash_str, (char*) sum)) + { + e->type = MD5SUM_VERIFY_FAIL; + file_close(f); + return 1; + } + file_close(f); + return 0; +} + +int +parse_group(xmlNode *cur, exception_t *e) +{ + char *type = NULL; + cur = cur->children; + while (cur != NULL) + { + if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, (const xmlChar*) "type")) + { + xmlChar *key = NULL; // xmlNodeGetContent(cur); + + /* if (cur->type != XML_ELEMENT_NODE) { */ + /* e->type = XML_READ_FILE_FAIL; */ + /* sprintf(e->msg, "not element node"); */ + /* return 1; */ + /* } */ + + /* for (xmlNode *child = cur->children; child; child = child->next) { */ + /* if (child->type == XML_ELEMENT_NODE) { */ + /* xmlChar *key = xmlNodeGetContent(child); */ + /* if (key == NULL) */ + /* continue; */ + + /* if (strlen((char *)key) == 0) { */ + /* xmlFree(key); */ + /* continue; */ + /* } */ + /* } */ + /* } */ + + if (key == NULL) { + e->type = XML_READ_FILE_FAIL; + sprintf(e->msg, "key == NULL: node type %i", cur->type); + return 1; + } + if (conf_verify_key(conf, (const char*) key, type) > 0) { + e->type = XML_READ_FILE_FAIL; + sprintf(e->msg, "Conf key fail: %s (%i)", (char*)key, xmlStrlen(key)); + xmlFree(key); + return 1; + } + xmlFree(key); + break; + } + cur = cur->next; + } + + while (cur != NULL) + { + if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, (const xmlChar*) "file")) + { + if (parse_file(cur, type, e) != 0) return 1; + } + cur = cur->next; + } + free(type); + return 0; +} + +static int +parse_file_list(xmlNode *cur, exception_t *e) +{ + cur = cur->children; + while (cur != NULL) + { + if (cur->type == XML_ELEMENT_NODE && xmlStrEqual(cur->name, (const xmlChar*) "group")) + { + if (parse_group(cur, e) != 0) return 1; + } + cur = cur->next; + } + return 0; +} + int verify(exception_t *e) { xmlDoc *doc = NULL; xmlNode *root_element, *cur_node; - - doc = xmlReadFile(paths_xml, NULL, 0); + // For testing only + file_t *f = file_init(paths_xml, FILEPATH_RELATIVE, e); + if (!exception_null(e)) return 1; + doc = xmlReadFile(f->name, NULL, 0); if (doc == NULL) { e->type = XML_FILE_MISSING; + file_close(f); return 1; } - root_element = xmlDocGetRootElement (doc); - - if (strcmp((const char*) root_element->name, "paths")) + + if (root_element->type != XML_ELEMENT_NODE || !xmlStrEqual(root_element->name, (const xmlChar*) "paths")) { e->type = XML_READ_FILE_FAIL; + sprintf(e->msg, "XML node %s (!= %s) of node no %i (!= %i)\n", (const char*) root_element->name, "paths", root_element->type, XML_ELEMENT_NODE); return 1; } - cur_node = root_element->children; - if (strcmp((const char*) cur_node->name, "file_list")) + while (cur_node != NULL) { - e->type = XML_READ_FILE_FAIL; - return 1; - } - - for (xmlNode *a_node = cur_node->children; strcmp((const char*) a_node->name, "group") != 0; a_node=a_node->next) - { - xmlNode *x_group_type = a_node->children; - for (xmlNode *b_node = x_group_type->next; strcmp((const char*) b_node->name, "file") != 0; b_node=b_node->next) - { - file_t *f; - xmlNode *x_name = b_node->children; - xmlNode *x_sum = x_name->next; - f = file_init((char*) x_name->content, FILEPATH_ABSOLUTE, e); - if (strcmp(f->hash_str, (char*) x_sum->content) != 0) - { - e->type = MD5SUM_VERIFY_FAIL; + if (cur_node->type == XML_ELEMENT_NODE && xmlStrEqual(cur_node->name, (const xmlChar*) "file_list")) + { + if (parse_file_list(cur_node, e) != 0) { + file_close(f); return 1; } - } + } + cur_node = cur_node->next; } + + file_close(f); return 0; } diff --git a/src/calibrate.h b/src/calibrate.h index d49e056..3d71e70 100644 --- a/src/calibrate.h +++ b/src/calibrate.h @@ -14,6 +14,8 @@ int replace_text(const char *file, const char *before, const char *after, const char *enc, exception_t *e); +// int parse_group(xmlNode *cur, exception_t *e); + /** * Check if each file has the same MD5hash sum as the one in paths.xml * @return 1 if error diff --git a/tests/check_calibrate.c b/tests/check_calibrate.c index 5a73b94..db1a932 100644 --- a/tests/check_calibrate.c +++ b/tests/check_calibrate.c @@ -1,5 +1,6 @@ #include #include +#include #include "check_check.h" #include "../src/calibrate.h" #include "../src/file_t.h" @@ -8,16 +9,49 @@ START_TEST(test_replace_text) { exception_t *e; file_t *f; + char except_msg[CHAR_MAX]; e = exception_init(); f = file_init("samples/1.txt", FILEPATH_RELATIVE, e); - char *path = file_abs(f); - ck_assert(replace_text(path, "ABC", "123", "ASCII", e)); - ck_assert(exception_null(e)); - ck_assert(replace_text(path, "123", "ABC", "ASCII", e)); - ck_assert(exception_null(e)); + ck_assert_msg(exception_null(e), exception_str(e, except_msg)); + replace_text(f->name, "ABC", "123", "ASCII", e); + ck_assert_msg(exception_null(e), exception_str(e, except_msg)); + replace_text(f->name, "123", "ABC", "ASCII", e); + ck_assert_msg(exception_null(e), exception_str(e, except_msg)); file_close(f); exception_free(e); - free(path); +} + +START_TEST(test_parse_group) +{ + exception_t *e; + char except_msg[CHAR_MAX]; + e = exception_init(); + + xmlDoc *doc = xmlReadFile("samples/1.xml", NULL, 0); + xmlNode *cur_node = xmlDocGetRootElement (doc); + + while (cur_node != NULL) + { + if (cur_node->type == XML_ELEMENT_NODE && xmlStrEqual(cur_node->name, (const xmlChar*) "group")) + { + parse_group(cur_node, e); + ck_assert_msg(exception_null(e), exception_str(e, except_msg)); + } + cur_node = cur_node->next; + } + + ck_assert_msg(exception_null(e), exception_str(e, except_msg)); + exception_free(e); +} + +START_TEST(test_verify) +{ + exception_t *e; + char except_msg[CHAR_MAX]; + e = exception_init(); + verify(e); + ck_assert_msg(exception_null(e), exception_str(e, except_msg)); + exception_free(e); } Suite* @@ -30,6 +64,8 @@ calibrate_suite(void) tc_core = tcase_create ("core"); tcase_add_test(tc_core, test_replace_text); + tcase_add_test(tc_core, test_parse_group); + tcase_add_test(tc_core, test_verify); suite_add_tcase(s, tc_core); return s;