1 /* mod-watchdog.c - Watchdog module for srvx
2 * Copyright 2003-2004 Martijn Smit and srvx Development Team
4 * This file is part of srvx.
6 * srvx 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.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 /* Adds new section to srvx.conf:
37 #define KEY_BADWORDS "badwords"
38 #define KEY_BADWORD_MASK "mask"
39 #define KEY_BADWORD_TRIGGERED "count"
40 #define KEY_BADWORD_ACTION "action"
41 #define KEY_CHANNELS "channel"
43 static const struct message_entry msgtab[] = {
44 { "WDMSG_NULL", "null." },
48 DECLARE_LIST(shitList, struct badword*);
49 DEFINE_LIST(shitList, struct badword*)
53 unsigned int triggered : 29;
54 unsigned int action : 3;
57 struct watchdog_channel {
58 struct chanNode *channel;
59 //struct shitList *shitlist;
62 /* badword.action fields */
63 #define BADACTION_KICK 1
64 #define BADACTION_KILL 2
65 #define BADACTION_GLINE 3
72 const char *watchdog_module_deps[] = { NULL };
73 struct userNode *watchdog;
74 static struct module *watchdog_module;
75 static struct service *watchdog_service;
76 static struct shitList shitlist;
77 static dict_t chanlist;
78 static struct log_type *MS_LOG;
81 static MODCMD_FUNC(cmd_addbad)
87 static MODCMD_FUNC(cmd_delbad)
93 static MODCMD_FUNC(cmd_editbad)
99 static MODCMD_FUNC(cmd_listbad)
105 static MODCMD_FUNC(cmd_register)
111 static MODCMD_FUNC(cmd_unregister)
118 watchdog_channel_message(struct userNode *user, struct chanNode *chan, const char *text, struct userNode *bot, unsigned int is_notice)
123 static struct badword*
124 add_badword(char *badword_mask, unsigned int triggered, unsigned int action)
126 struct badword *badword;
128 badword = calloc(1, sizeof(*badword));
132 badword->badword_mask = strdup(badword_mask);
133 badword->triggered = triggered;
134 badword->action = action;
135 shitList_append(&shitlist, badword);
140 delete_badword(struct badword *badword)
142 shitList_remove(&shitlist, badword);
143 free(badword->badword_mask);
147 static struct watchdog_channel*
148 add_channel(const char *name)
150 struct watchdog_channel *wc;
152 wc = calloc(1, sizeof(*wc));
156 wc->channel = AddChannel(name, now, NULL, NULL);
157 AddChannelUser(watchdog, wc->channel)->modes |= MODE_CHANOP;
158 dict_insert(chanlist, wc->channel->name, wc);
163 free_chanlist_entry(void *data)
165 struct watchdog_channel *wc = data;
171 watchdog_conf_read(void)
176 str = "modules/watchdog";
177 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
178 log_module(MS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
182 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
183 if(watchdog_conf.nick && strcmp(watchdog_conf.nick, str)) {
186 watchdog_conf.nick = str;
188 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
189 watchdog_conf.modes = (str ? str : NULL);
193 watchdog_saxdb_read_shitlist(const char *name, void *data, UNUSED_ARG(void *extra))
195 struct record_data *rd = data;
197 char *triggered, *action;
199 if (rd->type == RECDB_OBJECT) {
200 dict_t obj = GET_RECORD_OBJECT(rd);
201 /* new style structure */
202 badword = database_get_data(obj, KEY_BADWORD_MASK, RECDB_QSTRING);
203 triggered = database_get_data(obj, KEY_BADWORD_TRIGGERED, RECDB_QSTRING);
204 action = database_get_data(obj, KEY_BADWORD_ACTION, RECDB_QSTRING);
206 add_badword(badword, strtoul(triggered, NULL, 0), strtoul(action, NULL, 0));
213 watchdog_saxdb_read_chanlist(const char *name, void *data, UNUSED_ARG(void *extra))
215 struct record_data *rd = data;
217 if (rd->type == RECDB_OBJECT) {
218 dict_t obj = GET_RECORD_OBJECT(rd);
219 /* nothing in here, yet */
228 watchdog_saxdb_read(struct dict *db)
231 if ((object = database_get_data(db, KEY_BADWORDS, RECDB_OBJECT)))
232 dict_foreach(object, watchdog_saxdb_read_shitlist, NULL);
233 if ((object = database_get_data(db, KEY_CHANNELS, RECDB_OBJECT)))
234 dict_foreach(object, watchdog_saxdb_read_chanlist, NULL);
239 watchdog_saxdb_write(struct saxdb_context *ctx)
241 struct badword *badword;
243 unsigned int id = 0, ii;
246 saxdb_start_record(ctx, KEY_BADWORDS, 1);
247 for (ii = 0; ii < shitlist.used; ++ii) {
248 badword = shitlist.list[ii];
249 snprintf(str, sizeof(str), "%x", id++);
250 saxdb_start_record(ctx, str, 0);
251 saxdb_write_string(ctx, KEY_BADWORD_MASK, badword->badword_mask);
252 saxdb_write_int(ctx, KEY_BADWORD_TRIGGERED, badword->triggered);
253 saxdb_write_int(ctx, KEY_BADWORD_ACTION, badword->action);
254 saxdb_end_record(ctx);
256 saxdb_end_record(ctx);
258 if (dict_size(chanlist)) {
259 saxdb_start_record(ctx, KEY_CHANNELS, 1);
260 for (it = dict_first(chanlist); it; it = iter_next(it)) {
261 struct watchdog_channel *wc = iter_data(it);
262 saxdb_start_record(ctx, wc->channel->name, 0);
264 saxdb_end_record(ctx);
266 saxdb_end_record(ctx);
273 watchdog_cleanup(void)
275 while (shitlist.used)
276 delete_badword(shitlist.list[0]);
277 shitList_clean(&shitlist);
278 dict_delete(chanlist);
284 MS_LOG = log_register_type("Watchdog", "file:watchdog.log");
286 shitList_init(&shitlist);
287 /* set up chanlist dict */
288 dict_delete(chanlist);
289 chanlist = dict_new();
290 dict_set_free_data(chanlist, free_chanlist_entry);
292 conf_register_reload(watchdog_conf_read);
293 reg_exit_func(watchdog_cleanup);
294 saxdb_register("Watchdog", watchdog_saxdb_read, watchdog_saxdb_write);
296 const char *nick, *modes;
297 if((nick = conf_get_data("modules/watchdog/nick", RECDB_QSTRING))) {
298 modes = conf_get_data("modules/watchdog/modes", RECDB_QSTRING);
299 watchdog = AddLocalUser(nick, nick, NULL, "Watchdog Service", modes);
300 watchdog_service = service_register(watchdog);
301 reg_allchanmsg_func(watchdog, watchdog_channel_message);
304 watchdog_module = module_register("Watchdog", MS_LOG, "mod-watchdog.help", NULL);
305 modcmd_register(watchdog_module, "addbad", cmd_addbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
306 modcmd_register(watchdog_module, "delbad", cmd_delbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
307 modcmd_register(watchdog_module, "editbad", cmd_editbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
308 modcmd_register(watchdog_module, "listbad", cmd_listbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
309 modcmd_register(watchdog_module, "register", cmd_register, 1, MODCMD_REQUIRE_AUTHED, "flags", "+helping", NULL);
310 modcmd_register(watchdog_module, "unregister", cmd_unregister, 1, MODCMD_REQUIRE_AUTHED, "flags", "+helping", NULL);
311 message_register_table(msgtab);
317 watchdog_finalize(void) {
321 str = "modules/watchdog";
322 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
323 log_module(MS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
327 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
328 if (str) watchdog_conf.nick = str;
330 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
331 if (str) watchdog_conf.modes = str;