mirror of
https://github.com/irssi/irssi.git
synced 2026-08-22 10:02:22 +02:00
Introduce variable filtering in the config files
Prepending a '&' to a quoted string makes the given string to be filtered trough an user-supplied function. Right now it does return the value as-is.
This commit is contained in:
parent
795301f679
commit
a9a3dba50d
5 changed files with 66 additions and 9 deletions
|
|
@ -703,6 +703,13 @@ int irssi_config_is_changed(const char *fname)
|
||||||
config_last_checksum != file_checksum(fname));
|
config_last_checksum != file_checksum(fname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean filter_stub(const char *key, const char *value, char **new_value)
|
||||||
|
{
|
||||||
|
g_warning("Filtering %s in %s", value, key);
|
||||||
|
*new_value = (char *)value;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static CONFIG_REC *parse_configfile(const char *fname)
|
static CONFIG_REC *parse_configfile(const char *fname)
|
||||||
{
|
{
|
||||||
CONFIG_REC *config;
|
CONFIG_REC *config;
|
||||||
|
|
@ -736,6 +743,8 @@ static CONFIG_REC *parse_configfile(const char *fname)
|
||||||
config = config_open(NULL, -1);
|
config = config_open(NULL, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config_set_filter_function(filter_stub);
|
||||||
|
|
||||||
if (config->fname != NULL)
|
if (config->fname != NULL)
|
||||||
config_parse(config);
|
config_parse(config);
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@
|
||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
|
||||||
|
static ConfigFilterFunc filter_func = NULL;
|
||||||
|
|
||||||
CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key)
|
CONFIG_NODE *config_node_find(CONFIG_NODE *node, const char *key)
|
||||||
{
|
{
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
|
|
@ -165,7 +167,7 @@ CONFIG_NODE *config_node_traverse(CONFIG_REC *rec, const char *section, int crea
|
||||||
char *config_get_str(CONFIG_REC *rec, const char *section, const char *key, const char *def)
|
char *config_get_str(CONFIG_REC *rec, const char *section, const char *key, const char *def)
|
||||||
{
|
{
|
||||||
CONFIG_NODE *parent, *node;
|
CONFIG_NODE *parent, *node;
|
||||||
char *path;
|
char *path, *value;
|
||||||
|
|
||||||
g_return_val_if_fail(rec != NULL, (char *) def);
|
g_return_val_if_fail(rec != NULL, (char *) def);
|
||||||
g_return_val_if_fail(key != NULL, (char *) def);
|
g_return_val_if_fail(key != NULL, (char *) def);
|
||||||
|
|
@ -190,7 +192,18 @@ char *config_get_str(CONFIG_REC *rec, const char *section, const char *key, cons
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (node == NULL || !has_node_value(node)) ? (char *) def : node->value;
|
if (node == NULL || !has_node_value(node))
|
||||||
|
{
|
||||||
|
return (char *)def;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->do_filter && filter_func)
|
||||||
|
{
|
||||||
|
return filter_func(key, node->value, &value) ?
|
||||||
|
value : (char *)def;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int config_get_int(CONFIG_REC *rec, const char *section, const char *key, int def)
|
int config_get_int(CONFIG_REC *rec, const char *section, const char *key, int def)
|
||||||
|
|
@ -216,12 +229,24 @@ int config_get_bool(CONFIG_REC *rec, const char *section, const char *key, int d
|
||||||
char *config_node_get_str(CONFIG_NODE *parent, const char *key, const char *def)
|
char *config_node_get_str(CONFIG_NODE *parent, const char *key, const char *def)
|
||||||
{
|
{
|
||||||
CONFIG_NODE *node;
|
CONFIG_NODE *node;
|
||||||
|
char *value;
|
||||||
|
|
||||||
if (parent == NULL) return (char *) def;
|
if (parent == NULL) return (char *) def;
|
||||||
|
|
||||||
node = config_node_find(parent, key);
|
node = config_node_find(parent, key);
|
||||||
return (char *) ((node != NULL && has_node_value(node)) ?
|
|
||||||
node->value : def);
|
if (node == NULL || !has_node_value(node))
|
||||||
|
{
|
||||||
|
return (char *)def;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node->do_filter && filter_func)
|
||||||
|
{
|
||||||
|
return filter_func(key, node->value, &value) ?
|
||||||
|
value : (char *)def;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int config_node_get_int(CONFIG_NODE *parent, const char *key, int def)
|
int config_node_get_int(CONFIG_NODE *parent, const char *key, int def)
|
||||||
|
|
@ -339,3 +364,8 @@ GSList *config_node_next(GSList *list)
|
||||||
list = list->next;
|
list = list->next;
|
||||||
return config_node_first(list);
|
return config_node_first(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void config_set_filter_function(ConfigFilterFunc func)
|
||||||
|
{
|
||||||
|
filter_func = func;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,9 @@ typedef struct _CONFIG_NODE CONFIG_NODE;
|
||||||
typedef struct _CONFIG_REC CONFIG_REC;
|
typedef struct _CONFIG_REC CONFIG_REC;
|
||||||
|
|
||||||
struct _CONFIG_NODE {
|
struct _CONFIG_NODE {
|
||||||
int type;
|
int type : 8;
|
||||||
char *key;
|
int do_filter : 1;
|
||||||
|
char *key;
|
||||||
void *value;
|
void *value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -46,6 +47,10 @@ struct _CONFIG_NODE {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef gboolean (*ConfigFilterFunc)(const char *key,
|
||||||
|
const char *value,
|
||||||
|
char **new_value);
|
||||||
|
|
||||||
struct _CONFIG_REC {
|
struct _CONFIG_REC {
|
||||||
char *fname;
|
char *fname;
|
||||||
int create_mode;
|
int create_mode;
|
||||||
|
|
@ -72,6 +77,8 @@ CONFIG_REC *config_open(const char *fname, int create_mode);
|
||||||
void config_close(CONFIG_REC *rec);
|
void config_close(CONFIG_REC *rec);
|
||||||
/* Change file name of config file */
|
/* Change file name of config file */
|
||||||
void config_change_file_name(CONFIG_REC *rec, const char *fname, int create_mode);
|
void config_change_file_name(CONFIG_REC *rec, const char *fname, int create_mode);
|
||||||
|
/* Set the default function to handle the variable filtering */
|
||||||
|
void config_set_filter_function(ConfigFilterFunc func);
|
||||||
|
|
||||||
/* Parse configuration file */
|
/* Parse configuration file */
|
||||||
int config_parse(CONFIG_REC *rec);
|
int config_parse(CONFIG_REC *rec);
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ static GTokenType config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node)
|
||||||
{
|
{
|
||||||
CONFIG_NODE *newnode;
|
CONFIG_NODE *newnode;
|
||||||
GTokenType last_char;
|
GTokenType last_char;
|
||||||
int print_warning;
|
int print_warning, do_filter;
|
||||||
char *key;
|
char *key;
|
||||||
|
|
||||||
g_return_val_if_fail(rec != NULL, G_TOKEN_ERROR);
|
g_return_val_if_fail(rec != NULL, G_TOKEN_ERROR);
|
||||||
|
|
@ -151,12 +151,21 @@ static GTokenType config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node)
|
||||||
config_parse_get_token(rec->scanner, node);
|
config_parse_get_token(rec->scanner, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do_filter = FALSE;
|
||||||
|
|
||||||
switch (rec->scanner->token) {
|
switch (rec->scanner->token) {
|
||||||
|
case '&':
|
||||||
|
/* substitute value */
|
||||||
|
do_filter = TRUE;
|
||||||
|
config_parse_warn_missing(rec, node, G_TOKEN_STRING, TRUE);
|
||||||
|
g_assert(rec->scanner->token == G_TOKEN_STRING);
|
||||||
case G_TOKEN_STRING:
|
case G_TOKEN_STRING:
|
||||||
/* value */
|
/* value */
|
||||||
config_node_set_str(rec, node, key, rec->scanner->value.v_string);
|
newnode = config_node_set_str(rec, node, key, rec->scanner->value.v_string);
|
||||||
g_free_not_null(key);
|
g_free_not_null(key);
|
||||||
|
|
||||||
|
newnode->do_filter = do_filter;
|
||||||
|
|
||||||
print_warning = TRUE;
|
print_warning = TRUE;
|
||||||
if (node->type == NODE_TYPE_LIST) {
|
if (node->type == NODE_TYPE_LIST) {
|
||||||
/* if it's last item it doesn't need comma */
|
/* if it's last item it doesn't need comma */
|
||||||
|
|
@ -167,7 +176,6 @@ static GTokenType config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node)
|
||||||
|
|
||||||
config_parse_warn_missing(rec, node, last_char, print_warning);
|
config_parse_warn_missing(rec, node, last_char, print_warning);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '{':
|
case '{':
|
||||||
/* block */
|
/* block */
|
||||||
if (key == NULL && node->type != NODE_TYPE_LIST)
|
if (key == NULL && node->type != NODE_TYPE_LIST)
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,7 @@ static int config_write_node(CONFIG_REC *rec, CONFIG_NODE *node, int line_feeds)
|
||||||
case NODE_TYPE_KEY:
|
case NODE_TYPE_KEY:
|
||||||
if (config_write_word(rec, node->key, FALSE) == -1 ||
|
if (config_write_word(rec, node->key, FALSE) == -1 ||
|
||||||
config_write_str(rec, " = ") == -1 ||
|
config_write_str(rec, " = ") == -1 ||
|
||||||
|
(node->do_filter && config_write_str(rec, "&") == -1) ||
|
||||||
config_write_word(rec, node->value, TRUE) == -1)
|
config_write_word(rec, node->value, TRUE) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
|
|
@ -212,6 +213,8 @@ static int config_node_get_length(CONFIG_REC *rec, CONFIG_NODE *node)
|
||||||
case NODE_TYPE_KEY:
|
case NODE_TYPE_KEY:
|
||||||
/* "key = value; " */
|
/* "key = value; " */
|
||||||
len = 5 + strlen(node->key) + strlen(node->value);
|
len = 5 + strlen(node->key) + strlen(node->value);
|
||||||
|
/* optional '&' before the value */
|
||||||
|
len += node->do_filter ? 1 : 0;
|
||||||
break;
|
break;
|
||||||
case NODE_TYPE_VALUE:
|
case NODE_TYPE_VALUE:
|
||||||
/* "value, " */
|
/* "value, " */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue