#include #include #include #include #include #include "calibrate.h" #include "file_t.h" #include "conf.h" #include "paths.h" #define BUFFER_SIZE 1000 // 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. * @return 1 if error, * 0 otherwise */ static char* convert_text(const char *text, const char *enc, exception_t *e); /** * Replace all occurrences of a given a word in string. */ static void replaceAll(char *str, const char *oldWord, const char *newWord); /** * Replace a string of text with another in a text file * @param file Absolute path to file * @param before before * @param after after * @return 1 if error * 0 otherwise */ static int replace_text_encoded(const char *file, const char *before, const char *after, exception_t *e); static char* convert_text(const char *text, const char *enc, exception_t *e) { iconv_t to; size_t len_before, len_after; char *conv; to = iconv_open("UTF-8", enc); len_before = strlen(text); len_after = 2 * len_before; conv = calloc(len_after, sizeof(char)); if (iconv(to, &text, &len_before, &conv, &len_after) < 0) { printf("Error iconv"); return NULL; } iconv_close(iconv); return conv; } /** * Replace all occurrences of a given a word in string. */ static void replaceAll(char *str, const char *oldWord, const char *newWord) { char *pos, temp[BUFFER_SIZE]; int index = 0; int owlen; owlen = strlen(oldWord); /* Repeat till all occurrences are replaced. */ while ((pos = strstr(str, oldWord)) != NULL) { // Bakup current line strcpy(temp, str); // Index of current found word index = pos - str; // Terminate str after word found index str[index] = '\0'; // Concatenate str with new word strcat(str, newWord); // Concatenate str with remaining words after // oldword found index. strcat(str, temp + index + owlen); } } static int replace_text_encoded(const char *file, const char *before, const char *after, exception_t *e) { FILE *fPtr, *fTemp; char buffer[BUFFER_SIZE]; /* Open all required files */ fPtr = fopen(file, "r"); fTemp = fopen("replace.tmp", "w"); /* fopen() return NULL if unable to open file in given mode. */ if (fPtr == NULL || fTemp == NULL) { e->type = NO_FILE; return 1; } /* * Read line from source file and write to destination * file after replacing given word. */ while ((fgets(buffer, BUFFER_SIZE, fPtr)) != NULL) { // Replace all occurrence of word from current line replaceAll(buffer, before, after); // After replacing write it to temp file. fputs(buffer, fTemp); } /* Close all files to release resource */ fclose(fPtr); fclose(fTemp); /* Delete original source file */ remove(file); /* Rename temp file as original file */ rename("replace.tmp", file); remove("replace.tmp"); return 0; } int calibrate(exception_t *e) { /* Verify installation */ if (verify(e) > 0) { return 1; } /* Modify text */ if (edit(e) > 0) { return 1; } 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; // 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 (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; while (cur_node != NULL) { 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; } int edit(exception_t *e) { xmlDoc *doc = NULL; xmlNode *root_element, *cur_node; doc = xmlReadFile(paths_xml, NULL, 0); if (doc == NULL) { e->type = XML_FILE_MISSING; return 1; } root_element = xmlDocGetRootElement (doc); if (strcmp((const char*) root_element->name, "paths")) { e->type = XML_READ_FILE_FAIL; return 1; } cur_node = root_element->children; if (strcmp((const char*) cur_node->name, "edit_list")) { e->type = XML_READ_FILE_FAIL; return 1; } char *conf, *dir; size_t lendir; conf = ".config/modetw/modetw.conf"; 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; lendir = strlen((const char*) x_group_type); conf_verify_key(conf, (const char*) x_group_type, dir); for (xmlNode *b_node = x_group_type->next; strcmp((const char*) b_node->name, "edit") != 0; b_node=b_node->next) { size_t lenpath; file_t *f; xmlNode *x_path = b_node->children; xmlNode *x_before = x_path->next; xmlNode *x_after = x_before->next; xmlNode *x_type = x_after->next; lenpath = strlen(x_path); char fullpath[lenpath + lendir + 1]; strcat(fullpath, x_group_type); strcat(fullpath, "/"); strcat(fullpath, x_path); f = file_init(&fullpath, FILEPATH_ABSOLUTE, e); replace_text(f, x_before, x_after, x_type, e); file_close(f); } } return 0; } int replace_text(const char *file, const char *before, const char *after, const char *enc, exception_t *e) { if (strcmp(enc, "ASCII") == 0) { return replace_text_encoded(file, before, after, e); } return replace_text_encoded(file, convert_text(before, enc, e), convert_text(after, enc, e), e); }