fixed mod-watchdog.c basics
[srvx.git] / src / mod-watchdog.c
1 /* mod-watchdog.c - Watchdog module for srvx
2  * Copyright 2003-2004 Martijn Smit and srvx Development Team
3  *
4  * This file is part of srvx.
5  *
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.
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
17  * along with srvx; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
19  */
20
21 /* Adds new section to srvx.conf:
22  * "modules" {
23  *     "watchdog" {
24  *         "nick" "Watchdog";
25  *         "modes" "+iok"
26  *     };
27  *  };
28  *
29  */
30
31 #include "chanserv.h"
32 #include "conf.h"
33 #include "modcmd.h"
34 #include "saxdb.h"
35 #include "timeq.h"
36
37 #define KEY_BADWORDS "badwords"
38 #define KEY_BADWORD_MASK "mask"
39 #define KEY_BADWORD_TRIGGERED "count"
40 #define KEY_BADWORD_ACTION "action"
41
42 static const struct message_entry msgtab[] = {
43     { "WDMSG_NULL", "null." },
44     { NULL, NULL }
45 };
46
47 struct badword {
48     char *badword_mask;
49     unsigned int triggered : 29;
50     unsigned int action : 3;
51 };
52
53 DECLARE_LIST(shitList, struct badword*);
54 DEFINE_LIST(shitList, struct badword*)
55
56 /* badword.action fields */
57 #define BADACTION_KICK   1
58 #define BADACTION_KILL   2
59 #define BADACTION_GLINE  3
60
61 static struct {
62     const char *nick;
63     const char *modes;
64 } watchdog_conf;
65
66 const char *watchdog_module_deps[] = { NULL };
67 struct userNode *watchdog;
68 static struct module *watchdog_module;
69 static struct service *watchdog_service;
70 static struct shitList shitlist;
71 static struct log_type *MS_LOG;
72
73
74 static MODCMD_FUNC(cmd_addbad)
75 {
76     //to be continued...
77     return 1;
78 }
79
80 static MODCMD_FUNC(cmd_delbad)
81 {
82     //to be continued...
83     return 1;
84 }
85
86 static MODCMD_FUNC(cmd_editbad)
87 {
88     //to be continued...
89     return 1;
90 }
91
92 static MODCMD_FUNC(cmd_listbad)
93 {
94     //to be continued...
95     return 1;
96 }
97
98 static void
99 watchdog_channel_message(struct userNode *user, struct chanNode *chan, const char *text, struct userNode *bot, unsigned int is_notice)
100 {
101     //to be continued...
102 }
103
104 static struct badword*
105 add_badword(char *badword_mask, unsigned int triggered, unsigned int action)
106 {
107     struct badword *badword;
108
109     badword = calloc(1, sizeof(*badword));
110     if (!badword)
111         return NULL;
112
113     badword->badword_mask = strdup(badword_mask);
114     badword->triggered = triggered;
115     badword->action = action;
116     shitList_append(&shitlist, badword);
117     return badword;
118 }
119
120 static void
121 delete_badword(struct badword *badword)
122 {
123     shitList_remove(&shitlist, badword);
124     free(badword->badword_mask);
125     free(badword);
126 }
127
128 static void
129 watchdog_conf_read(void)
130 {
131     dict_t conf_node;
132     const char *str;
133
134     str = "modules/watchdog";
135     if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
136         log_module(MS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
137         return;
138     }
139
140     str = database_get_data(conf_node, "nick", RECDB_QSTRING);
141     if(watchdog_conf.nick && strcmp(watchdog_conf.nick, str)) {
142         //nick changed
143     }
144     watchdog_conf.nick = str;
145     
146     str = database_get_data(conf_node, "modes", RECDB_QSTRING);
147     watchdog_conf.modes = (str ? str : NULL);
148 }
149
150 static int
151 watchdog_saxdb_read_shitlist(const char *name, void *data, UNUSED_ARG(void *extra))
152 {
153     struct record_data *rd = data;
154     char *badword;
155     char *triggered, *action;
156
157      if (rd->type == RECDB_OBJECT) {
158         dict_t obj = GET_RECORD_OBJECT(rd);
159         /* new style structure */
160         badword = database_get_data(obj, KEY_BADWORD_MASK, RECDB_QSTRING);
161         triggered = database_get_data(obj, KEY_BADWORD_TRIGGERED, RECDB_QSTRING);
162         action = database_get_data(obj, KEY_BADWORD_ACTION, RECDB_QSTRING);
163
164         add_badword(badword, strtoul(triggered, NULL, 0), strtoul(action, NULL, 0));
165         return 1;
166     } else
167         return 0;
168 }
169
170 static int
171 watchdog_saxdb_read(struct dict *db)
172 {
173     struct dict *object;
174     if ((object = database_get_data(db, KEY_BADWORDS, RECDB_OBJECT)))
175         dict_foreach(object, watchdog_saxdb_read_shitlist, NULL);
176     return 1;
177 }
178
179 static int
180 watchdog_saxdb_write(struct saxdb_context *ctx)
181 {
182     struct badword *badword;
183     char str[17];
184     unsigned int id = 0, ii;
185
186     saxdb_start_record(ctx, KEY_BADWORDS, 1);
187     for (ii = 0; ii < shitlist.used; ++ii) {
188         badword = shitlist.list[ii];
189         snprintf(str, sizeof(str), "%x", id++);
190         saxdb_start_record(ctx, str, 0);
191         saxdb_write_string(ctx, KEY_BADWORD_MASK, badword->badword_mask);
192         saxdb_write_int(ctx, KEY_BADWORD_TRIGGERED, badword->triggered);
193         saxdb_write_int(ctx, KEY_BADWORD_ACTION, badword->action);
194         saxdb_end_record(ctx);
195     }
196     saxdb_end_record(ctx);
197
198     return 0;
199 }
200
201 static void
202 watchdog_cleanup(void)
203 {
204     while (shitlist.used)
205         delete_badword(shitlist.list[0]);
206     shitList_clean(&shitlist);
207 }
208
209 int
210 watchdog_init(void)
211 {
212     MS_LOG = log_register_type("Watchdog", "file:watchdog.log");
213     shitList_init(&shitlist);
214     conf_register_reload(watchdog_conf_read);
215     reg_exit_func(watchdog_cleanup);
216     saxdb_register("Watchdog", watchdog_saxdb_read, watchdog_saxdb_write);
217
218     const char *nick, *modes;
219     if((nick = conf_get_data("services/watchdog/nick", RECDB_QSTRING))) {
220         modes = conf_get_data("services/watchdog/modes", RECDB_QSTRING);
221         watchdog = AddLocalUser(nick, nick, NULL, "Watchdog Service", modes);
222         watchdog_service = service_register(watchdog);
223         reg_allchanmsg_func(watchdog, watchdog_channel_message);
224     }
225
226     watchdog_module = module_register("Watchdog", MS_LOG, "mod-watchdog.help", NULL);
227     modcmd_register(watchdog_module, "addbad", cmd_addbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
228     modcmd_register(watchdog_module, "delbad", cmd_delbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
229     modcmd_register(watchdog_module, "editbad", cmd_editbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
230     modcmd_register(watchdog_module, "listbad", cmd_listbad, 1, MODCMD_REQUIRE_AUTHED, "flags", "+oper", NULL);
231     message_register_table(msgtab);
232
233     return 1;
234 }
235
236 int
237 watchdog_finalize(void) {
238     dict_t conf_node;
239     const char *str;
240
241     str = "modules/watchdog";
242     if (!(conf_node = conf_get_data(str, RECDB_OBJECT))) {
243         log_module(MS_LOG, LOG_ERROR, "config node `%s' is missing or has wrong type.", str);
244         return 0;
245     }
246
247     str = database_get_data(conf_node, "nick", RECDB_QSTRING);
248     if (str) watchdog_conf.nick = str;
249     
250     str = database_get_data(conf_node, "modes", RECDB_QSTRING);
251     if (str) watchdog_conf.modes = str;
252     return 1;
253 }