Coverage Report

Created: 2025-07-18 07:25

/src/irssi/src/core/channels-setup.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 channels-setup.c : irssi
3
4
    Copyright (C) 1999-2000 Timo Sirainen
5
6
    This program is free software; you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
10
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
16
    You should have received a copy of the GNU General Public License along
17
    with this program; if not, write to the Free Software Foundation, Inc.,
18
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
*/
20
21
#include "module.h"
22
#include <irssi/src/core/signals.h>
23
#include <irssi/src/lib-config/iconfig.h>
24
#include <irssi/src/core/settings.h>
25
26
#include <irssi/src/core/chat-protocols.h>
27
#include <irssi/src/core/chatnets.h>
28
#include <irssi/src/core/servers-setup.h>
29
#include <irssi/src/core/channels-setup.h>
30
31
GSList *setupchannels;
32
33
static int compare_channel_setup (CONFIG_NODE *node, CHANNEL_SETUP_REC *channel)
34
0
{
35
0
  char *name, *chatnet;
36
37
  /* skip comment nodes */
38
0
  if (node->type == NODE_TYPE_COMMENT)
39
0
    return -1;
40
41
0
  name = config_node_get_str(node, "name", NULL);
42
0
  chatnet = config_node_get_str(node, "chatnet", NULL);
43
44
0
  if (name == NULL || chatnet == NULL) {
45
0
    return 0;
46
0
  }
47
48
0
  if (g_ascii_strcasecmp(name, channel->name) != 0 ||
49
0
      g_ascii_strcasecmp(chatnet, channel->chatnet) != 0) {
50
0
    return 1;
51
0
  }
52
53
0
  return 0;
54
0
}
55
56
static void channel_setup_save(CHANNEL_SETUP_REC *channel)
57
0
{
58
0
  CONFIG_NODE *parent_node, *node;
59
0
  GSList *config_node;
60
61
0
  parent_node = iconfig_node_traverse("(channels", TRUE);
62
63
  /* Try to find this channel in the configuration */
64
0
  config_node = g_slist_find_custom(parent_node->value, channel,
65
0
            (GCompareFunc)compare_channel_setup);
66
0
  if (config_node != NULL)
67
    /* Let's update this channel record */
68
0
    node = config_node->data;
69
0
  else
70
    /* Create a brand-new channel record */
71
0
    node = iconfig_node_section(parent_node, NULL, NODE_TYPE_BLOCK);
72
73
0
        iconfig_node_clear(node);
74
0
  iconfig_node_set_str(node, "name", channel->name);
75
0
  iconfig_node_set_str(node, "chatnet", channel->chatnet);
76
0
  if (channel->autojoin)
77
0
    iconfig_node_set_bool(node, "autojoin", TRUE);
78
0
  iconfig_node_set_str(node, "password", channel->password);
79
0
  iconfig_node_set_str(node, "botmasks", channel->botmasks);
80
0
  iconfig_node_set_str(node, "autosendcmd", channel->autosendcmd);
81
0
}
82
83
void channel_setup_create(CHANNEL_SETUP_REC *channel)
84
0
{
85
0
  channel->type = module_get_uniq_id("CHANNEL SETUP", 0);
86
87
0
  if (g_slist_find(setupchannels, channel) == NULL)
88
0
    setupchannels = g_slist_append(setupchannels, channel);
89
0
  channel_setup_save(channel);
90
91
0
  signal_emit("channel setup created", 1, channel);
92
0
}
93
94
static void channel_config_remove(CHANNEL_SETUP_REC *channel)
95
0
{
96
0
  CONFIG_NODE *parent_node;
97
0
  GSList *config_node;
98
99
0
  parent_node = iconfig_node_traverse("channels", FALSE);
100
101
0
  if (parent_node == NULL)
102
0
    return;
103
104
  /* Try to find this channel in the configuration */
105
0
  config_node = g_slist_find_custom(parent_node->value, channel,
106
0
            (GCompareFunc)compare_channel_setup);
107
108
0
  if (config_node != NULL)
109
    /* Delete the channel from the configuration */
110
0
    iconfig_node_remove(parent_node, config_node->data);
111
0
}
112
113
static void channel_setup_destroy(CHANNEL_SETUP_REC *channel)
114
0
{
115
0
  g_return_if_fail(channel != NULL);
116
117
0
  setupchannels = g_slist_remove(setupchannels, channel);
118
0
  signal_emit("channel setup destroyed", 1, channel);
119
120
0
  g_free_not_null(channel->chatnet);
121
0
  g_free_not_null(channel->password);
122
0
  g_free_not_null(channel->botmasks);
123
0
  g_free_not_null(channel->autosendcmd);
124
0
  g_free(channel->name);
125
0
  g_free(channel);
126
0
}
127
128
void channel_setup_remove_chatnet(const char *chatnet)
129
0
{
130
0
  GSList *tmp, *next;
131
132
0
  g_return_if_fail(chatnet != NULL);
133
134
0
  for (tmp = setupchannels; tmp != NULL; tmp = next) {
135
0
    CHANNEL_SETUP_REC *rec = tmp->data;
136
137
0
    next = tmp->next;
138
0
    if (g_ascii_strcasecmp(rec->chatnet, chatnet) == 0)
139
0
      channel_setup_remove(rec);
140
0
  }
141
0
}
142
143
void channel_setup_remove(CHANNEL_SETUP_REC *channel)
144
0
{
145
0
        channel_config_remove(channel);
146
0
        channel_setup_destroy(channel);
147
0
}
148
149
CHANNEL_SETUP_REC *channel_setup_find(const char *channel,
150
              const char *chatnet)
151
33.2k
{
152
33.2k
  GSList *tmp;
153
154
33.2k
  g_return_val_if_fail(channel != NULL, NULL);
155
156
299k
  for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) {
157
265k
    CHANNEL_SETUP_REC *rec = tmp->data;
158
159
265k
    if (g_ascii_strcasecmp(rec->name, channel) == 0 &&
160
265k
        channel_chatnet_match(rec->chatnet, chatnet))
161
0
      return rec;
162
265k
  }
163
164
33.2k
  return NULL;
165
33.2k
}
166
167
static CHANNEL_SETUP_REC *channel_setup_read(CONFIG_NODE *node)
168
18
{
169
18
  CHANNEL_SETUP_REC *rec;
170
18
        CHATNET_REC *chatnetrec;
171
18
  char *channel, *chatnet;
172
173
18
  g_return_val_if_fail(node != NULL, NULL);
174
175
18
  channel = config_node_get_str(node, "name", NULL);
176
18
        chatnet = config_node_get_str(node, "chatnet", NULL);
177
178
18
  chatnetrec = chatnet == NULL ? NULL : chatnet_find(chatnet);
179
18
  if (channel == NULL || chatnetrec == NULL) {
180
    /* missing information.. */
181
2
    return NULL;
182
2
  }
183
184
16
  rec = CHAT_PROTOCOL(chatnetrec)->create_channel_setup();
185
16
  rec->type = module_get_uniq_id("CHANNEL SETUP", 0);
186
16
  rec->chat_type = CHAT_PROTOCOL(chatnetrec)->id;
187
16
  rec->autojoin = config_node_get_bool(node, "autojoin", FALSE);
188
16
  rec->name = g_strdup(channel);
189
16
  rec->chatnet = g_strdup(chatnetrec != NULL ? chatnetrec->name : chatnet);
190
16
  rec->password = g_strdup(config_node_get_str(node, "password", NULL));
191
16
  rec->botmasks = g_strdup(config_node_get_str(node, "botmasks", NULL));
192
16
  rec->autosendcmd = g_strdup(config_node_get_str(node, "autosendcmd", NULL));
193
194
16
  setupchannels = g_slist_append(setupchannels, rec);
195
16
  signal_emit("channel setup created", 2, rec, node);
196
16
  return rec;
197
18
}
198
199
static void channels_read_config(void)
200
2
{
201
2
  CONFIG_NODE *node;
202
2
  GSList *tmp;
203
204
2
  while (setupchannels != NULL)
205
0
    channel_setup_destroy(setupchannels->data);
206
207
  /* Read channels */
208
2
  node = iconfig_node_traverse("channels", FALSE);
209
2
  if (node != NULL) {
210
2
    int i = 0;
211
2
    tmp = config_node_first(node->value);
212
20
    for (; tmp != NULL; tmp = config_node_next(tmp), i++) {
213
18
      node = tmp->data;
214
18
      if (node->type != NODE_TYPE_BLOCK) {
215
0
        g_critical("Expected block node at `channels[%d]' was of %s type. "
216
0
                   "Corrupt config?",
217
0
                   i, node->type == NODE_TYPE_LIST ? "list" : "scalar");
218
18
      } else {
219
18
        channel_setup_read(node);
220
18
      }
221
18
    }
222
2
  }
223
2
}
224
225
void channels_setup_init(void)
226
8
{
227
8
        setupchannels = NULL;
228
8
  source_host_ok = FALSE;
229
230
8
  signal_add("setup reread channels", (SIGNAL_FUNC) channels_read_config);
231
8
}
232
233
void channels_setup_deinit(void)
234
0
{
235
0
  while (setupchannels != NULL)
236
0
    channel_setup_destroy(setupchannels->data);
237
238
0
  signal_remove("setup reread channels", (SIGNAL_FUNC) channels_read_config);
239
0
}