#include #include #include #include #include #include "calibrate.h" #include "file_t.h" #include "conf.h" #include "paths.h" #define BUFFER_SIZE 1000 static const char* paths_xml = "/.local/modetw/paths.xml"; /** * 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) { /* 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"); 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); 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; } int verify(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, "file_list")) { 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; return 1; } } } 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); }