Coverage Report

Created: 2026-08-13 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/irssi/src/core/chatnets.c
Line
Count
Source
1
/*
2
 chatnets.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/network.h>
23
#include <irssi/src/core/signals.h>
24
#include <irssi/src/core/special-vars.h>
25
#include <irssi/src/lib-config/iconfig.h>
26
#include <irssi/src/core/settings.h>
27
#include <irssi/src/core/misc.h>
28
29
#include <irssi/src/core/chat-protocols.h>
30
#include <irssi/src/core/chatnets.h>
31
#include <irssi/src/core/servers.h>
32
33
GSList *chatnets, *chatnets_unavailable; /* list of available chat networks */
34
35
static void chatnet_config_save(CHATNET_REC *chatnet)
36
0
{
37
0
  CONFIG_NODE *node;
38
39
0
  node = iconfig_node_traverse("chatnets", TRUE);
40
0
  node = iconfig_node_section(node, chatnet->name, NODE_TYPE_BLOCK);
41
0
  iconfig_node_clear(node);
42
43
0
  iconfig_node_set_str(node, "type", chat_protocol_find_id(chatnet->chat_type)->name);
44
0
  iconfig_node_set_str(node, "nick", chatnet->nick);
45
0
  iconfig_node_set_str(node, "username", chatnet->username);
46
0
  iconfig_node_set_str(node, "realname", chatnet->realname);
47
0
  iconfig_node_set_str(node, "host", chatnet->own_host);
48
0
  iconfig_node_set_str(node, "autosendcmd", chatnet->autosendcmd);
49
50
0
        signal_emit("chatnet saved", 2, chatnet, node);
51
0
}
52
53
static void chatnet_config_remove(CHATNET_REC *chatnet)
54
0
{
55
0
  CONFIG_NODE *node;
56
57
0
  node = iconfig_node_traverse("chatnets", FALSE);
58
0
  if (node != NULL) iconfig_node_set_str(node, chatnet->name, NULL);
59
0
}
60
61
void chatnet_create(CHATNET_REC *chatnet)
62
0
{
63
0
  g_return_if_fail(chatnet != NULL);
64
0
  g_return_if_fail(!CHAT_PROTOCOL(chatnet)->not_initialized);
65
66
0
  chatnet->type = module_get_uniq_id("CHATNET", 0);
67
0
  if (g_slist_find(chatnets, chatnet) == NULL)
68
0
    chatnets = g_slist_append(chatnets, chatnet);
69
70
0
  chatnet_config_save(chatnet);
71
0
  signal_emit("chatnet created", 1, chatnet);
72
0
}
73
74
void chatnet_remove(CHATNET_REC *chatnet)
75
0
{
76
0
  g_return_if_fail(IS_CHATNET(chatnet));
77
78
0
  signal_emit("chatnet removed", 1, chatnet);
79
80
0
  chatnet_config_remove(chatnet);
81
0
  chatnet_destroy(chatnet);
82
0
}
83
84
void chatnet_destroy(CHATNET_REC *chatnet)
85
0
{
86
0
  g_return_if_fail(IS_CHATNET(chatnet));
87
88
0
  chatnets = g_slist_remove(chatnets, chatnet);
89
0
  signal_emit("chatnet destroyed", 1, chatnet);
90
91
0
  g_free_not_null(chatnet->nick);
92
0
  g_free_not_null(chatnet->username);
93
0
  g_free_not_null(chatnet->realname);
94
0
  g_free_not_null(chatnet->own_host);
95
0
  g_free_not_null(chatnet->autosendcmd);
96
0
  g_free(chatnet->name);
97
0
  g_free(chatnet);
98
0
}
99
100
/* Find the chat network by name */
101
CHATNET_REC *chatnet_find(const char *name)
102
90.5k
{
103
90.5k
  GSList *tmp;
104
105
90.5k
  g_return_val_if_fail(name != NULL, NULL);
106
107
1.17M
  for (tmp = chatnets; tmp != NULL; tmp = tmp->next) {
108
1.08M
    CHATNET_REC *rec = tmp->data;
109
110
1.08M
    if (g_ascii_strcasecmp(rec->name, name) == 0)
111
42
      return rec;
112
1.08M
  }
113
114
90.5k
  return NULL;
115
90.5k
}
116
117
gboolean chatnet_find_unavailable(const char *name)
118
2
{
119
2
  CHAT_PROTOCOL_REC *proto;
120
121
2
  if (i_slist_find_icase_string(chatnets_unavailable, name) != NULL)
122
2
    return TRUE;
123
124
0
  proto = CHAT_PROTOCOL(chatnet_find(name));
125
126
0
  if (proto == NULL || proto->not_initialized)
127
0
    return TRUE;
128
129
0
  return FALSE;
130
0
}
131
132
static void sig_connected(SERVER_REC *server)
133
19.6k
{
134
19.6k
  CHATNET_REC *rec;
135
136
19.6k
  g_return_if_fail(IS_SERVER(server));
137
138
19.6k
  if (server->connrec->chatnet == NULL || server->session_reconnect)
139
19.6k
    return;
140
141
0
  rec = chatnet_find(server->connrec->chatnet);
142
0
  if (!server->connrec->no_autosendcmd && rec != NULL && rec->autosendcmd)
143
0
    eval_special_string(rec->autosendcmd, "", server, NULL);
144
0
}
145
146
static void chatnet_read(CONFIG_NODE *node)
147
26
{
148
26
        CHAT_PROTOCOL_REC *proto;
149
26
  CHATNET_REC *rec;
150
26
        char *type;
151
152
26
  if (node == NULL || node->key == NULL || !is_node_list(node))
153
0
    return;
154
155
26
  type = config_node_get_str(node, "type", NULL);
156
26
  if (type == NULL) {
157
0
    proto = chat_protocol_get_default();
158
26
  } else {
159
26
    proto = chat_protocol_find(type);
160
26
  }
161
162
26
  if (proto == NULL) {
163
    /* protocol not loaded */
164
2
    if (i_slist_find_icase_string(chatnets_unavailable, node->key) == NULL)
165
2
      chatnets_unavailable =
166
2
          g_slist_append(chatnets_unavailable, g_strdup(node->key));
167
168
2
    return;
169
24
  } else if (type == NULL) {
170
0
    iconfig_node_set_str(node, "type", proto->name);
171
0
  }
172
173
24
  rec = proto->create_chatnet();
174
24
  rec->type = module_get_uniq_id("CHATNET", 0);
175
24
  rec->chat_type = proto->id;
176
24
  rec->name = g_strdup(node->key);
177
24
  rec->nick = g_strdup(config_node_get_str(node, "nick", NULL));
178
24
  rec->username = g_strdup(config_node_get_str(node, "username", NULL));
179
24
  rec->realname = g_strdup(config_node_get_str(node, "realname", NULL));
180
24
  rec->own_host = g_strdup(config_node_get_str(node, "host", NULL));
181
24
  rec->autosendcmd = g_strdup(config_node_get_str(node, "autosendcmd", NULL));
182
183
24
  chatnets = g_slist_append(chatnets, rec);
184
24
        signal_emit("chatnet read", 2, rec, node);
185
24
}
186
187
static void read_chatnets(void)
188
2
{
189
2
  CONFIG_NODE *node;
190
2
        GSList *tmp;
191
192
2
  while (chatnets != NULL)
193
0
                chatnet_destroy(chatnets->data);
194
195
2
  while (chatnets_unavailable != NULL) {
196
0
    char *name = chatnets_unavailable->data;
197
0
    chatnets_unavailable = g_slist_remove(chatnets_unavailable, name);
198
0
    g_free(name);
199
0
  }
200
201
2
  node = iconfig_node_traverse("chatnets", FALSE);
202
2
  if (node != NULL) {
203
2
    tmp = config_node_first(node->value);
204
28
    for (; tmp != NULL; tmp = config_node_next(tmp))
205
26
                        chatnet_read(tmp->data);
206
2
  }
207
2
}
208
209
void chatnets_init(void)
210
8
{
211
8
  chatnets = NULL;
212
213
8
  signal_add_first("event connected", (SIGNAL_FUNC) sig_connected);
214
8
  signal_add("setup reread chatnets", (SIGNAL_FUNC) read_chatnets);
215
8
}
216
217
void chatnets_deinit(void)
218
0
{
219
0
  module_uniq_destroy("CHATNET");
220
221
0
  signal_remove("event connected", (SIGNAL_FUNC) sig_connected);
222
  signal_remove("setup reread chatnets", (SIGNAL_FUNC) read_chatnets);
223
0
}