/* Chrysalide - Outil d'analyse de fichiers binaires
* configuration.c - éléments de configuration du programme
*
* Copyright (C) 2009-2014 Cyrille Bagard
*
* This file is part of Chrysalide.
*
* OpenIDA is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* OpenIDA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar. If not, see .
*/
#include "configuration.h"
#include
#include
#include
#include
#include
#include
#include "common/extstr.h"
#include "common/xdg.h"
#include "common/xml.h"
/* Paramètres de configuration */
struct _configuration
{
config_param *params; /* Paramètres à consulter */
unsigned int count; /* Quantité de ces paramètres */
char *filename; /* Fichier externe */
xmlDocPtr xdoc; /* Document XML de configurat° */
xmlXPathContextPtr context; /* Contexte de recherche XPath */
};
/* S'assure qu'un chemin donné existe dans le système. */
static int ensure_path_exists(const char *);
/******************************************************************************
* *
* Paramètres : name = désignation de la configuration. *
* params = tableau de paramètres à consulter / mettre à jour. *
* count = taille du tableau en question. *
* *
* Description : Charge la configuration principale. *
* *
* Retour : Configuration prête à emploi. *
* *
* Remarques : - *
* *
******************************************************************************/
configuration *load_configuration(const char *name, config_param *params, unsigned int count)
{
configuration *result; /* Structure à retourner */
char *suffix; /* Fin du nom de fichier */
unsigned int i; /* Boucle de parcours */
char *strval; /* Valeur en chaîne de carac. */
result = (configuration *)calloc(1, sizeof(configuration));
for (i = 0; i < count; i++)
params[i].cur = params[i].def;
result->params = params;
result->count = count;
suffix = strdup("openida/");
suffix = stradd(suffix, name);
suffix = stradd(suffix, ".xml");
result->filename = get_xdg_config_dir(suffix);
free(suffix);
if (!open_xml_file(result->filename, &result->xdoc, &result->context))
create_new_xml_file(&result->xdoc, &result->context);
else
for (i = 0; i < count; i++)
switch (params[i].type)
{
case CVT_BOOLEAN:
strval = get_node_text_value(result->context, params[i].path);
if (strval != NULL)
{
set_boolean_config_value(result, i, strcmp(strval, "true") == 0);
free(strval);
}
break;
case CVT_INTEGER:
strval = get_node_text_value(result->context, params[i].path);
if (strval != NULL)
{
set_integer_config_value(result, i, atoi(strval));
free(strval);
}
break;
case CVT_STRING:
strval = get_node_text_value(result->context, params[i].path);
set_string_config_value(result, i, strval);
if (strval != NULL) free(strval);
break;
default:
break;
}
return result;
}
/******************************************************************************
* *
* Paramètres : path = chemin d'accès à valider. *
* *
* Description : S'assure qu'un chemin donné existe dans le système. *
* *
* Retour : 0 si le chemin est actuellement présent, -1 sinon. *
* *
* Remarques : - *
* *
******************************************************************************/
static int ensure_path_exists(const char *path)
{
int result; /* Bilan de l'assurance */
char *tmp; /* Chemin altérable */
tmp = strdup(path);
tmp = dirname(tmp);
result = access(tmp, W_OK | X_OK);
if (result != 0)
{
result = ensure_path_exists(tmp);
if (result == 0)
result = mkdir(tmp, 0700);
}
free(tmp);
return result;
}
/******************************************************************************
* *
* Paramètres : config = configuration à libérer de la mémoire. *
* *
* Description : Décharge la configuration principale. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void unload_configuration(configuration *config)
{
int ret; /* Bilan de l'assurance */
unsigned int i; /* Boucle de parcours */
config_param *params; /* Confort d'utilisation */
char tmp[12 /* -INT_MIN */]; /* Reconstruction en chaîne */
close_xml_file(config->xdoc, config->context);
ret = ensure_path_exists(config->filename);
if (ret != 0) goto uc_exit;
create_new_xml_file(&config->xdoc, &config->context);
for (i = 0; i < config->count; i++)
{
params = &config->params[i];
switch (params->type)
{
case CVT_BOOLEAN:
if (params->cur.boolean == params->def.boolean)
continue;
add_content_to_node(config->xdoc, config->context,
params->path,
params->cur.boolean ? "true" : "false");
break;
case CVT_INTEGER:
if (params->cur.integer == params->def.integer)
continue;
snprintf(tmp, 12, "%d", params->cur.integer);
add_content_to_node(config->xdoc, config->context,
params->path, tmp);
break;
case CVT_STRING:
if (params->cur.string == NULL && params->def.string == NULL)
continue;
if (params->def.string != NULL && params->def.string != NULL
&& strcmp(params->cur.string, params->def.string) == 0)
continue;
add_content_to_node(config->xdoc, config->context,
params->path,
params->cur.string != NULL ? params->cur.string : "");
break;
default:
break;
}
}
save_xml_file(config->xdoc, config->filename);
uc_exit:
free(config);
}
/******************************************************************************
* *
* Paramètres : config = configuration à venir consulter. *
* index = indice de l'élément à traiter. *
* value = valeur à considérer comme valeur courante. *
* *
* Description : Définit une valeur booléenne dans la configuration. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
bool set_boolean_config_value(configuration *config, unsigned int index, bool value)
{
if (index >= config->count) return false;
if (config->params[index].type != CVT_BOOLEAN) return false;
config->params[index].defined = true;
config->params[index].cur.boolean = value;
return true;
}
/******************************************************************************
* *
* Paramètres : config = configuration à venir consulter. *
* index = indice de l'élément à traiter. *
* *
* Description : Fournit une valeur booléenne issue de la configuration. *
* *
* Retour : Valeur courante ou par défaut de la configuration. *
* *
* Remarques : - *
* *
******************************************************************************/
bool get_boolean_config_value(configuration *config, unsigned int index)
{
bool result; /* Valeur à retourner */
if (index >= config->count) return false;
if (config->params[index].type != CVT_BOOLEAN) return false;
if (config->params[index].defined) result = config->params[index].cur.boolean;
else result = config->params[index].def.boolean;
return result;
}
/******************************************************************************
* *
* Paramètres : config = configuration à venir consulter. *
* index = indice de l'élément à traiter. *
* value = valeur à considérer comme valeur courante. *
* *
* Description : Définit une valeur entière dans la configuration. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
bool set_integer_config_value(configuration *config, unsigned int index, int value)
{
if (index >= config->count) return false;
if (config->params[index].type != CVT_INTEGER) return false;
config->params[index].defined = true;
config->params[index].cur.integer = value;
return true;
}
/******************************************************************************
* *
* Paramètres : config = configuration à venir consulter. *
* index = indice de l'élément à traiter. *
* *
* Description : Fournit une valeur entière issue de la configuration. *
* *
* Retour : Valeur courante ou par défaut de la configuration. *
* *
* Remarques : - *
* *
******************************************************************************/
int get_integer_config_value(configuration *config, unsigned int index)
{
int result; /* Valeur à retourner */
if (index >= config->count) return 0;
if (config->params[index].type != CVT_INTEGER) return 0;
if (config->params[index].defined) result = config->params[index].cur.integer;
else result = config->params[index].def.integer;
return result;
}
/******************************************************************************
* *
* Paramètres : config = configuration à venir consulter. *
* index = indice de l'élément à traiter. *
* value = valeur à considérer comme valeur courante. *
* *
* Description : Définit une chaîne de caractères dans la configuration. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
bool set_string_config_value(configuration *config, unsigned int index, const char *value)
{
if (index >= config->count) return false;
if (config->params[index].type != CVT_STRING) return false;
config->params[index].defined = true;
if (config->params[index].cur.string != NULL)
free(config->params[index].cur.string);
config->params[index].cur.string = (value != NULL ? strdup(value) : NULL);
return true;
}
/******************************************************************************
* *
* Paramètres : config = configuration à venir consulter. *
* index = indice de l'élément à traiter. *
* *
* Description : Fournit une chaîne de caractères issue de la configuration. *
* *
* Retour : Valeur courante ou par défaut de la configuration. *
* *
* Remarques : - *
* *
******************************************************************************/
const char *get_string_config_value(configuration *config, unsigned int index)
{
const char *result; /* Valeur à retourner */
if (index >= config->count) return NULL;
if (config->params[index].type != CVT_STRING) return NULL;
if (config->params[index].defined) result = config->params[index].cur.string;
else result = config->params[index].def.string;
return result;
}