272 lines
6.3 KiB
C
272 lines
6.3 KiB
C
|
#include <libxml2/libxml/parser.h>
|
||
|
#include <libxml2/libxml/tree.h>
|
||
|
#include <string.h>
|
||
|
#include <iconv.h>
|
||
|
#include <limits.h>
|
||
|
|
||
|
#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, e, "HOME");
|
||
|
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, e, "HOME");
|
||
|
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);
|
||
|
}
|