1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

Rewrite some faulty logic handling the saved channels.

Issue #340 brought to our attention the fact that under certain
circumstances irssi would go on a wild rampage and carelessly overwrite
some saved channel records in the configuration file.
This happened because the code didn't take into account the case where
the channel index in setupchannels wouldn't match the one in the
configuration; this actually happens when the user removes a chatnet
without removing the associated channels.
This commit is contained in:
LemonBoy 2015-12-06 22:31:49 +01:00
parent b5cfa55d9b
commit 750df38e8c

View File

@ -30,16 +30,34 @@
GSList *setupchannels; GSList *setupchannels;
static int compare_channel_name (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel)
{
char *name, *chatnet;
name = config_node_get_str(node, "name", NULL);
chatnet = config_node_get_str(node, "chatnet", NULL);
if (name == NULL || chatnet == NULL)
return 1;
return !!strcmp(name, channel->name) | !!strcmp(chatnet, channel->chatnet);
}
static void channel_setup_save(CHANNEL_SETUP_REC *channel) static void channel_setup_save(CHANNEL_SETUP_REC *channel)
{ {
CONFIG_NODE *parentnode, *node; CONFIG_NODE *parentnode, *node;
int index; GSList *config_node;
index = g_slist_index(setupchannels, channel);
parentnode = iconfig_node_traverse("(channels", TRUE); parentnode = iconfig_node_traverse("(channels", TRUE);
node = config_node_nth(parentnode, index);
if (node == NULL) /* Try to find this channel in the configuration */
config_node = g_slist_find_custom(parentnode->value, channel,
(GCompareFunc)compare_channel_name);
if (config_node != NULL)
/* Let's update this channel record */
node = config_node->data;
else
/* Create a brand-new channel record */
node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK); node = iconfig_node_section(parentnode, NULL, NODE_TYPE_BLOCK);
iconfig_node_clear(node); iconfig_node_clear(node);
@ -65,10 +83,21 @@ void channel_setup_create(CHANNEL_SETUP_REC *channel)
static void channel_config_remove(CHANNEL_SETUP_REC *channel) static void channel_config_remove(CHANNEL_SETUP_REC *channel)
{ {
CONFIG_NODE *node; CONFIG_NODE *parentnode;
GSList *config_node;
node = iconfig_node_traverse("channels", FALSE); parentnode = iconfig_node_traverse("channels", FALSE);
if (node != NULL) iconfig_node_list_remove(node, g_slist_index(setupchannels, channel));
if (parentnode == NULL)
return;
/* Try to find this channel in the configuration */
config_node = g_slist_find_custom(parentnode->value, channel,
(GCompareFunc)compare_channel_name);
if (config_node != NULL)
/* Delete the channel from the configuration */
iconfig_node_remove(parentnode, config_node->data);
} }
static void channel_setup_destroy(CHANNEL_SETUP_REC *channel) static void channel_setup_destroy(CHANNEL_SETUP_REC *channel)