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 { "WD_REGISTER_SUCCESS", "$b%s$b is now registered with %s." },
45 { "WD_NOT_REGISTERED", "$b%s$b is not registered with %s." },
49 DECLARE_LIST(shitList, struct badword*);
50 DEFINE_LIST(shitList, struct badword*)
54 unsigned int triggered : 29;
55 unsigned int action : 3;
58 struct watchdog_channel {
59 struct chanNode *channel;
60 //struct shitList *shitlist;
63 /* badword.action fields */
64 #define BADACTION_KICK 1
65 #define BADACTION_KILL 2
66 #define BADACTION_GLINE 3
73 const char *watchdog_module_deps[] = { NULL };
74 struct userNode *watchdog;
75 static struct module *watchdog_module;
76 static struct service *watchdog_service;
77 static struct shitList shitlist;
78 static dict_t chanlist;
79 static struct log_type *MS_LOG;
82 static MODCMD_FUNC(cmd_addbad)
88 static MODCMD_FUNC(cmd_delbad)
94 static MODCMD_FUNC(cmd_editbad)
100 static MODCMD_FUNC(cmd_listbad)
106 static struct watchdog_channel *add_channel(const char *name);
108 static MODCMD_FUNC(cmd_register)
112 if((argc < 2) || !IsChannelName(argv[1]))
114 reply("MSG_NOT_CHANNEL_NAME");
118 if(opserv_bad_channel(argv[1]))
120 reply("CSMSG_ILLEGAL_CHANNEL", argv[1]);
124 channel = AddChannel(argv[1], now, NULL, NULL);
126 for (it = dict_first(chanlist); it; it = iter_next(it)) {
127 struct watchdog_channel *chan = iter_data(it);
128 if(chan->channel == channel) {
129 reply("CSMSG_ALREADY_REGGED", channel->name);
134 add_channel(channel->name);
135 reply("WD_REGISTER_SUCCESS", channel->name, watchdog->nick);
139 static MODCMD_FUNC(cmd_unregister)
141 struct watchdog_channel *chan = NULL;
144 for (it = dict_first(chanlist); it; it = iter_next(it)) {
145 chan = iter_data(it);
146 if(chan->channel == channel)
150 if(chan && chan->channel == channel) {
151 //found, unregister it!
152 DelChannelUser(watchdog, channel, "unregistered.", 0);
153 dict_remove(chanlist, channel->name);
154 reply("CSMSG_UNREG_SUCCESS", channel->name);
157 reply("WD_NOT_REGISTERED", channel->name, watchdog->nick);
164 watchdog_channel_message(struct userNode *user, struct chanNode *chan, const char *text, struct userNode *bot, unsigned int is_notice)
169 static struct badword*
170 add_badword(char *badword_mask, unsigned int triggered, unsigned int action)
172 struct badword *badword;
174 badword = calloc(1, sizeof(*badword));
178 badword->badword_mask = strdup(badword_mask);
179 badword->triggered = triggered;
180 badword->action = action;
181 shitList_append(&shitlist, badword);
186 delete_badword(struct badword *badword)
188 shitList_remove(&shitlist, badword);
189 free(badword->badword_mask);
193 static struct watchdog_channel*
194 add_channel(const char *name)
196 struct watchdog_channel *wc;
197 struct mod_chanmode *change;
199 if(!watchdog) //module disabled
202 wc = calloc(1, sizeof(*wc));
206 wc->channel = AddChannel(name, now, NULL, NULL);
207 change = mod_chanmode_alloc(1);
209 change->args[0].mode = MODE_CHANOP;
210 change->args[0].u.member = AddChannelUser(watchdog, wc->channel);
211 mod_chanmode_announce(watchdog, wc->channel, change);
212 mod_chanmode_free(change);
213 dict_insert(chanlist, wc->channel->name, wc);
218 free_chanlist_entry(void *data)
220 struct watchdog_channel *wc = data;
226 watchdog_conf_read(void)
231 str = "modules/watchdog";
232 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
233 log_module(MS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
237 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
238 if(watchdog_conf.nick && strcmp(watchdog_conf.nick, str)) {
241 watchdog_conf.nick = str;
243 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
244 watchdog_conf.modes = (str ? str : NULL);
248 watchdog_saxdb_read_shitlist(const char *name, void *data, UNUSED_ARG(void *extra))
250 struct record_data *rd = data;
252 char *triggered, *action;
254 if (rd->type == RECDB_OBJECT) {
255 dict_t obj = GET_RECORD_OBJECT(rd);
256 /* new style structure */
257 badword = database_get_data(obj, KEY_BADWORD_MASK, RECDB_QSTRING);
258 triggered = database_get_data(obj, KEY_BADWORD_TRIGGERED, RECDB_QSTRING);
259 action = database_get_data(obj, KEY_BADWORD_ACTION, RECDB_QSTRING);
261 add_badword(badword, strtoul(triggered, NULL, 0), strtoul(action, NULL, 0));
268 watchdog_saxdb_read_chanlist(const char *name, void *data, UNUSED_ARG(void *extra))
270 struct record_data *rd = data;
272 if (rd->type == RECDB_OBJECT) {
273 dict_t obj = GET_RECORD_OBJECT(rd);
274 /* nothing in here, yet */
283 watchdog_saxdb_read(struct dict *db)
286 if ((object = database_get_data(db, KEY_BADWORDS, RECDB_OBJECT)))
287 dict_foreach(object, watchdog_saxdb_read_shitlist, NULL);
288 if ((object = database_get_data(db, KEY_CHANNELS, RECDB_OBJECT)))
289 dict_foreach(object, watchdog_saxdb_read_chanlist, NULL);
294 watchdog_saxdb_write(struct saxdb_context *ctx)
296 struct badword *badword;
298 unsigned int id = 0, ii;
301 saxdb_start_record(ctx, KEY_BADWORDS, 1);
302 for (ii = 0; ii < shitlist.used; ++ii) {
303 badword = shitlist.list[ii];
304 snprintf(str, sizeof(str), "%x", id++);
305 saxdb_start_record(ctx, str, 0);
306 saxdb_write_string(ctx, KEY_BADWORD_MASK, badword->badword_mask);
307 saxdb_write_int(ctx, KEY_BADWORD_TRIGGERED, badword->triggered);
308 saxdb_write_int(ctx, KEY_BADWORD_ACTION, badword->action);
309 saxdb_end_record(ctx);
311 saxdb_end_record(ctx);
313 if (dict_size(chanlist)) {
314 saxdb_start_record(ctx, KEY_CHANNELS, 1);
315 for (it = dict_first(chanlist); it; it = iter_next(it)) {
316 struct watchdog_channel *wc = iter_data(it);
317 saxdb_start_record(ctx, wc->channel->name, 0);
319 saxdb_end_record(ctx);
321 saxdb_end_record(ctx);
328 watchdog_cleanup(void)
330 while (shitlist.used)
331 delete_badword(shitlist.list[0]);
332 shitList_clean(&shitlist);
333 dict_delete(chanlist);
339 MS_LOG = log_register_type("Watchdog", "file:watchdog.log");
341 shitList_init(&shitlist);
342 /* set up chanlist dict */
343 dict_delete(chanlist);
344 chanlist = dict_new();
345 dict_set_free_data(chanlist, free_chanlist_entry);
347 const char *nick, *modes;
348 if((nick = conf_get_data("modules/watchdog/nick", RECDB_QSTRING))) {
349 modes = conf_get_data("modules/watchdog/modes", RECDB_QSTRING);
350 watchdog = AddLocalUser(nick, nick, NULL, "Watchdog Service", modes);
351 watchdog_service = service_register(watchdog);
352 watchdog_service->trigger = ',';
353 reg_allchanmsg_func(watchdog, watchdog_channel_message);
356 conf_register_reload(watchdog_conf_read);
357 reg_exit_func(watchdog_cleanup);
358 saxdb_register("Watchdog", watchdog_saxdb_read, watchdog_saxdb_write);
360 watchdog_module = module_register("Watchdog", MS_LOG, "mod-watchdog.help", NULL);
361 modcmd_register(watchdog_module, "addbad", cmd_addbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
362 modcmd_register(watchdog_module, "delbad", cmd_delbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
363 modcmd_register(watchdog_module, "editbad", cmd_editbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
364 modcmd_register(watchdog_module, "listbad", cmd_listbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
365 modcmd_register(watchdog_module, "register", cmd_register, 1, MODCMD_REQUIRE_AUTHED, "flags", "+helping", NULL);
366 modcmd_register(watchdog_module, "unregister", cmd_unregister, 1, MODCMD_REQUIRE_AUTHED | MODCMD_REQUIRE_CHANNEL, "flags", "+helping", NULL);
367 message_register_table(msgtab);
373 watchdog_finalize(void) {
377 str = "modules/watchdog";
378 if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
379 log_module(MS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
383 str = database_get_data(conf_node, "nick", RECDB_QSTRING);
384 if (str) watchdog_conf.nick = str;
386 str = database_get_data(conf_node, "modes", RECDB_QSTRING);
387 if (str) watchdog_conf.modes = str;