]> jfr.im git - irc/evilnet/x3.git/blob - src/mod-snoop.c
Added a couple mode missing channel autojoin modes (for mod-snoop and mod-track)
[irc/evilnet/x3.git] / src / mod-snoop.c
1 /* mod-snoop.c - User surveillance module (per pomac's spec)
2 * Copyright 2002-2004 srvx Development Team
3 *
4 * This file is part of x3.
5 *
6 * x3 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 3 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 * "snoop" {
24 * // Where to send snoop messages?
25 * "channel" "#wherever";
26 * // Which bot?
27 * "bot" "OpServ";
28 * // Show new users and joins from net joins? (off by default)
29 * "show_bursts" "0";
30 * };
31 * };
32 */
33
34 #include "conf.h"
35 #include "helpfile.h"
36 #include "nickserv.h"
37
38 #ifdef HAVE_NETINET_IN_H
39 #include <netinet/in.h>
40 #endif
41 #ifdef HAVE_ARPA_INET_H
42 #include <arpa/inet.h>
43 #endif
44
45 extern time_t now;
46 static struct {
47 struct chanNode *channel;
48 struct userNode *bot;
49 unsigned int show_bursts : 1;
50 unsigned int enabled : 1;
51 } snoop_cfg;
52 static char timestamp[16];
53 const char *snoop_module_deps[] = { NULL };
54
55 static int finalized;
56 int snoop_finalize(void);
57
58 #if defined(GCC_VARMACROS)
59 # define SNOOP(FORMAT, ARGS...) send_channel_message(snoop_cfg.channel, snoop_cfg.bot, "%s "FORMAT, timestamp, ARGS)
60 #elif defined(C99_VARMACROS)
61 # define SNOOP(FORMAT, ...) send_channel_message(snoop_cfg.channel, snoop_cfg.bot, "%s "FORMAT, timestamp, __VA_ARGS__)
62 #endif
63 #define UPDATE_TIMESTAMP() strftime(timestamp, sizeof(timestamp), "[%H:%M:%S]", localtime(&now))
64
65 static void
66 snoop_nick_change(struct userNode *user, const char *old_nick, UNUSED_ARG(void *extra)) {
67 if (!snoop_cfg.enabled) return;
68 UPDATE_TIMESTAMP();
69 SNOOP("$bNICK$b change %s -> %s", old_nick, user->nick);
70 }
71
72 static int
73 snoop_join(struct modeNode *mNode, UNUSED_ARG(void *extra)) {
74 struct userNode *user = mNode->user;
75 struct chanNode *chan = mNode->channel;
76 if (!snoop_cfg.enabled) return 0;
77 if (user->uplink->burst && !snoop_cfg.show_bursts) return 0;
78 UPDATE_TIMESTAMP();
79 if (chan->members.used == 1) {
80 SNOOP("$bCREATE$b %s by %s", chan->name, user->nick);
81 } else {
82 SNOOP("$bJOIN$b %s by %s", chan->name, user->nick);
83 }
84 return 0;
85 }
86
87 static void
88 snoop_part(struct modeNode *mn, const char *reason, UNUSED_ARG(void *extra)) {
89 if (!snoop_cfg.enabled) return;
90 if (mn->user->dead) return;
91 UPDATE_TIMESTAMP();
92 SNOOP("$bPART$b %s by %s (%s)", mn->channel->name, mn->user->nick, reason ? reason : "");
93 }
94
95 static void
96 snoop_kick(struct userNode *kicker, struct userNode *victim, struct chanNode *chan, UNUSED_ARG(void *extra)) {
97 if (!snoop_cfg.enabled) return;
98 UPDATE_TIMESTAMP();
99 SNOOP("$bKICK$b %s from %s by %s", victim->nick, chan->name, (kicker ? kicker->nick : "some server"));
100 }
101
102 static int
103 snoop_new_user(struct userNode *user, UNUSED_ARG(void *extra)) {
104 if (!snoop_cfg.enabled) return 0;
105 if (user->uplink->burst && !snoop_cfg.show_bursts) return 0;
106 UPDATE_TIMESTAMP();
107 SNOOP("$bNICK$b %s %s@%s (%s) [%s] on %s", user->nick, user->ident, user->hostname, user->handle_info?user->handle_info->handle:"", irc_ntoa(&user->ip), user->uplink->name);
108 return 0;
109 }
110
111 static void
112 snoop_del_user(struct userNode *user, struct userNode *killer, const char *why, UNUSED_ARG(void *extra)) {
113 if (!snoop_cfg.enabled) return;
114 UPDATE_TIMESTAMP();
115 if (killer) {
116 SNOOP("$bKILL$b %s (%s@%s, on %s) by %s (%s)", user->nick, user->ident, user->hostname, user->uplink->name, killer->nick, why);
117 } else {
118 SNOOP("$bQUIT$b %s (%s@%s, on %s) (%s)", user->nick, user->ident, user->hostname, user->uplink->name, why);
119 }
120 }
121
122 static void
123 snoop_auth(struct userNode *user, UNUSED_ARG(struct handle_info *old_handle), UNUSED_ARG(void *extra)) {
124 if (!snoop_cfg.enabled) return;
125 if (user->uplink->burst && !snoop_cfg.show_bursts) return;
126 if (user->handle_info) {
127 UPDATE_TIMESTAMP();
128 /* TODO: show old_handle info -> new handle info if they
129 * re-authed or something.
130 */
131 SNOOP("$bAUTH$b %s as %s", user->nick, user->handle_info->handle);
132 }
133 }
134
135 static void
136 snoop_user_mode(struct userNode *user, const char *mode_change, UNUSED_ARG(void *extra)) {
137 if (!snoop_cfg.enabled) return;
138 if (user->uplink->burst && !snoop_cfg.show_bursts) return;
139 if (!mode_change[1]) return; /* warning there has to be atleast one char in the buffer */
140 UPDATE_TIMESTAMP();
141 SNOOP("$bUMODE$b %s %s", user->nick, mode_change);
142 }
143
144 static void
145 snoop_oper(struct userNode *user, UNUSED_ARG(void *extra)) {
146 if (!snoop_cfg.enabled) return;
147 if (user->uplink->burst && !snoop_cfg.show_bursts) return;
148 UPDATE_TIMESTAMP();
149 SNOOP("$bOPER$b %s!%s@%s [%s] on %s", user->nick, user->ident, user->hostname, irc_ntoa(&user->ip), user->uplink->name);
150 }
151
152 static void
153 snoop_channel_mode(struct userNode *who, struct chanNode *channel, char **modes, unsigned int argc, UNUSED_ARG(void *extra))
154 {
155 if (!snoop_cfg.enabled) return;
156 if(who) {
157 if (who->uplink->burst && !snoop_cfg.show_bursts) {
158 return;
159 }
160 } else {
161 return; /* Dont show X3 etc modes */
162 }
163
164 static char targets[MAXLEN], string[MAXLEN];
165 struct userNode *un = NULL;
166 char *tmp = NULL, *tg = NULL, *md = NULL;
167 int add = 0;
168
169 string[0] = 0;
170 targets[0] = 0;
171
172 if (argc > 0)
173 unsplit_string(modes, argc, string);
174 else
175 strcpy(string, *modes);
176
177 if((tg = strchr(string, ' ')))
178 {
179 *tg++ = 0;
180 for(md = string; *md; md++)
181 {
182 if (*md == '+')
183 {
184 add = 1;
185 md++;
186 }
187 if (*md == '-')
188 {
189 add = 0;
190 md++;
191 }
192 switch(*md)
193 {
194 case 'k':
195 {
196 strcat(targets, " ");
197 if ((tmp = strchr(tg, ' ')))
198 *tmp++ = 0;
199 strcat(targets, tg);
200 if(tmp)
201 tg = tmp;
202 break;
203 }
204 case 'l':
205 {
206 if(add)
207 {
208 strcat(targets, " ");
209 if ((tmp = strchr(tg, ' ')))
210 *tmp++ = 0;
211 strcat(targets, tg);
212 if(tmp)
213 tg = tmp;
214 break;
215 }
216 }
217 case 'b':
218 {
219 strcat(targets, " ");
220 if ((tmp = strchr(tg, ' ')))
221 *tmp++ = 0;
222 strcat(targets, tg);
223 if(tmp)
224 tg = tmp;
225 break;
226 }
227 case 'e':
228 {
229 strcat(targets, " ");
230 if ((tmp = strchr(tg, ' ')))
231 *tmp++ = 0;
232 strcat(targets, tg);
233 if(tmp)
234 tg = tmp;
235 break;
236 }
237 case 'o':
238 {
239 strcat(targets, " ");
240 if ((tmp = strchr(tg, ' ')))
241 *tmp++ = 0;
242 if((un = GetUserN(tg)))
243 strcat(targets, un->nick);
244 else
245 strcat(targets, tg);
246 if(tmp)
247 tg = tmp;
248 break;
249 }
250 case 'h':
251 {
252 strcat(targets, " ");
253 if ((tmp = strchr(tg, ' ')))
254 *tmp++ = 0;
255 if((un = GetUserN(tg)))
256 strcat(targets, un->nick);
257 else
258 strcat(targets, tg);
259 if(tmp)
260 tg = tmp;
261 break;
262 }
263 case 'v':
264 {
265 strcat(targets, " ");
266 if ((tmp = strchr(tg, ' ')))
267 *tmp++ = 0;
268 if((un = GetUserN(tg)))
269 strcat(targets, un->nick);
270 else
271 strcat(targets, tg);
272 if(tmp)
273 tg = tmp;
274 break;
275 }
276 }
277 }
278 }
279 UPDATE_TIMESTAMP();
280 if (who)
281 SNOOP("$bMODE$b %s %s%s by %s", channel->name, string, targets, who->nick);
282 else
283 SNOOP("$bMODE$b %s %s%s", channel->name, string, targets);
284 }
285
286 static void
287 snoop_conf_read(void) {
288 dict_t node;
289 char *str, *modes;
290
291 node = conf_get_data("modules/snoop", RECDB_OBJECT);
292 if (!node)
293 return;
294 str = database_get_data(node, "channel", RECDB_QSTRING);
295 modes = database_get_data(node, "channel_modes", RECDB_QSTRING);
296 if (!str)
297 return;
298 snoop_cfg.channel = AddChannel(str, now, (modes ? modes : "+sntim"), NULL, NULL);
299 if (!snoop_cfg.channel)
300 return;
301 str = database_get_data(node, "show_bursts", RECDB_QSTRING);
302 snoop_cfg.show_bursts = str ? enabled_string(str) : 0;
303 snoop_cfg.enabled = 1;
304 if (finalized)
305 snoop_finalize();
306 }
307
308 void
309 snoop_cleanup(UNUSED_ARG(void *extra)) {
310 snoop_cfg.enabled = 0;
311 unreg_del_user_func(snoop_del_user, NULL);
312 }
313
314 int
315 snoop_init(void) {
316 reg_exit_func(snoop_cleanup, NULL);
317 conf_register_reload(snoop_conf_read);
318 reg_nick_change_func(snoop_nick_change, NULL);
319 reg_join_func(snoop_join, NULL);
320 reg_part_func(snoop_part, NULL);
321 reg_kick_func(snoop_kick, NULL);
322 reg_new_user_func(snoop_new_user, NULL);
323 reg_del_user_func(snoop_del_user, NULL);
324 reg_auth_func(snoop_auth, NULL);
325 reg_channel_mode_func(snoop_channel_mode, NULL);
326 reg_user_mode_func(snoop_user_mode, NULL);
327 reg_oper_func(snoop_oper, NULL);
328
329 return 1;
330 }
331
332 int
333 snoop_finalize(void) {
334 struct mod_chanmode change;
335 dict_t node;
336 char *str;
337
338 finalized = 1;
339 node = conf_get_data("modules/snoop", RECDB_OBJECT);
340 if (!node)
341 return 0;
342 str = database_get_data(node, "bot", RECDB_QSTRING);
343 if (!str)
344 return 0;
345 snoop_cfg.bot = GetUserH(str);
346 if (!snoop_cfg.bot)
347 return 0;
348 mod_chanmode_init(&change);
349 change.argc = 1;
350 change.args[0].mode = MODE_CHANOP;
351 change.args[0].u.member = AddChannelUser(snoop_cfg.bot, snoop_cfg.channel);
352 mod_chanmode_announce(snoop_cfg.bot, snoop_cfg.channel, &change);
353 return 1;
354 }