]> jfr.im git - irc/quakenet/newserv.git/blob - helpmod2/hhooks.c
GLINES: fix null pointer deref in trustgline / trustungline
[irc/quakenet/newserv.git] / helpmod2 / hhooks.c
1 #include <string.h>
2 #include <assert.h>
3
4 #include "helpmod.h"
5 #include "hchannel.h"
6 #include "haccount.h"
7 #include "huser.h"
8 #include "hban.h"
9 #include "hqueue.h"
10 #include "hgen.h"
11 #include "hstat.h"
12 /*
13 void helpmod_hook_quit(int unused, void *args)
14 {
15 nick *nck = ((nick**)args)[0];
16 huser *husr = huser_get(nck);
17 / * it was someone we didn't even know * /
18 if (husr == NULL)
19 return;
20 }
21 */
22
23 /*
24 void helpmod_hook_part(int unused, void *args)
25 {
26 channel *chan = ((channel**)args)[0];
27 hchannel *hchan = hchannel_get_by_channel(chan);
28 nick *nck = ((nick**)args)[1];
29 huser *husr;
30
31 }
32 */
33 static void helpmod_hook_join(int unused, void *args)
34 {
35 channel *chan = ((channel**)args)[0];
36 hchannel *hchan = hchannel_get_by_channel(chan);
37 nick *nck = ((nick**)args)[1];
38 huser *husr;
39
40 /* if we're not on this channel or the target is G, the event is of no interest */
41 if (hchan == NULL || nck == helpmodnick)
42 return;
43
44 husr = huser_get(nck);
45
46 assert(husr != NULL); /* hook_channel_newnick should fix this */
47
48 if ((hchan->flags & H_JOINFLOOD_PROTECTION) && !(hchan->flags & H_PASSIVE))
49 {
50 if (hchan->jf_control < time(NULL))
51 hchan->jf_control = time(NULL);
52 else
53 hchan->jf_control++;
54
55 if (hchan->jf_control - time(NULL) > 12 && !IsRegOnly(hchan))
56 {
57 if (hchan->flags & H_REPORT && hchannel_is_valid(hchan->report_to))
58 helpmod_message_channel(hchan->report_to, "Warning: Possible join flood on %s, setting +r", hchannel_get_name(hchan));
59 hchannel_activate_join_flood(hchan);
60 }
61 }
62
63 if (hchan->flags & H_PASSIVE)
64 return;
65
66 if (hchan->flags & H_DO_STATS)
67 hstat_add_join(hchan);
68
69 if (hchan->flags & H_TROJAN_REMOVAL && huser_is_trojan(husr))
70 {
71 hban_huser(husr, "Trojan client", time(NULL) + 4 * HDEF_d, 1);
72 return;
73 }
74
75 if (huser_get_level(husr) >= H_STAFF && (huser_get_account_flags(husr) & H_AUTO_OP) && hchannel_authority(hchan, husr))
76 helpmod_channick_modes(husr, hchan ,MC_OP,HNOW);
77
78 if (huser_get_level(husr) >= H_TRIAL && (huser_get_account_flags(husr) & H_AUTO_VOICE) && hchannel_authority(hchan, husr))
79 helpmod_channick_modes(husr, hchan, MC_VOICE,HNOW);
80
81 if (hchan->flags & H_WELCOME && *hchan->real_channel->index->name->content)
82 helpmod_reply(husr, chan, "[%s] %s", hchan->real_channel->index->name->content, hchan->welcome);
83
84
85 if (hchan->flags & H_QUEUE && hchan->flags & H_QUEUE_SPAMMY)
86 {
87 if (huser_get_level(husr) < H_STAFF)
88 helpmod_reply(husr, NULL, "Channel %s is using a queue system. This means you will have to wait for support. Your queue position is #%d and currently the average time in queue is %s. Please wait for your turn and do not attempt to contact channel operators directly", hchannel_get_name(hchan), hqueue_get_position(hchan, husr), helpmod_strtime(hqueue_average_time(hchan)));
89 }
90 if (IsModerated(hchan->real_channel) && !(hchan->flags & H_QUEUE) && (hchan->flags & H_ANTI_IDLE))
91 { /* being nice to users */
92 if (huser_get_level(husr) < H_STAFF)
93 helpmod_reply(husr, NULL, "Channel %s is currently moderated and there are anti-idle measures in place. This usually means that there is no one to handle your problem at this time. Please try again later and don't forget to read the FAQ at www.quakenet.org", hchannel_get_name(hchan));
94 }
95 }
96
97 static void helpmod_hook_channel_newnick(int unused, void *args)
98 {
99 channel *chan = ((channel**)args)[0];
100 hchannel *hchan = hchannel_get_by_channel(chan);
101 nick *nck = ((nick**)args)[1];
102 huser *husr;
103
104 /* if we're not on this channel or the target is G, the event is of no interest */
105 if (hchan == NULL || nck == helpmodnick)
106 return;
107
108 if ((husr = huser_get(nck)) == NULL)
109 husr = huser_add(nck);
110
111 assert(huser_on_channel(husr, hchan) == NULL);
112 assert(hchannel_on_channel(hchan, husr) == NULL);
113
114 hchannel_add_user(hchan, husr);
115 huser_add_channel(husr, hchan);
116
117 if (hchan->flags & H_PASSIVE)
118 return;
119
120 huser_activity(husr, NULL);
121
122 if (huser_get_level(husr) == H_LAMER || (huser_get_level(husr) <= H_TRIAL && hban_check(nck)))
123 {
124 hban *hb = hban_check(nck);
125
126 const char *banmask = hban_ban_string(nck, HBAN_HOST);
127 helpmod_setban(hchan, banmask, time(NULL) + 1 * HDEF_d, MCB_ADD, HNOW);
128
129 if (hb)
130 helpmod_kick(hchan, husr, "%s", hban_get_reason(hb));
131 else
132 helpmod_kick(hchan, husr, "Your presence on channel %s is not wanted", hchannel_get_name(hchan));
133
134 return;
135 }
136 if (hchan->flags & H_QUEUE)
137 hqueue_handle_queue(hchan, NULL);
138 }
139
140 static void helpmod_hook_channel_lostnick(int unused, void *args)
141 {
142 channel *chan = ((channel**)args)[0];
143 hchannel *hchan = hchannel_get_by_channel(chan);
144 huser_channel *huserchan;
145 nick *nck = ((nick**)args)[1];
146 huser *husr;
147
148 /* In event that G was kicked, nothing is done */
149 if (nck == helpmodnick)
150 return;
151
152 /* hackery, can't think of a better way to do this */
153 huser *oper = NULL;
154 int handle_queue = 0;
155
156 /* if we're not on this channel, the event is of no interest */
157 if (hchan == NULL)
158 return;
159
160 husr = huser_get(nck);
161
162 assert(husr != NULL);
163
164 huserchan = huser_on_channel(husr, hchan);
165
166 assert(hchannel_on_channel(hchan, husr) != NULL);
167 assert(huserchan != NULL);
168
169 if ((hchan->flags & H_QUEUE) && (hchan->flags & H_QUEUE_MAINTAIN) && !(hchan->flags & H_PASSIVE)) /* && (huser_get_level(husr) == H_PEON) && (huserchan->flags & HCUMODE_VOICE) && (hchannel_count_queue(hchan)))*/
170 if (serverlist[homeserver(husr->real_user->numeric)].linkstate != LS_SQUIT)
171 /* if it was a netsplit, we do not trigger autoqueue */
172 {
173 oper = huserchan->responsible_oper;
174 handle_queue = !0;
175 }
176
177 hchannel_del_user(hchan, husr);
178 huser_del_channel(husr, hchan);
179
180 if (nck == helpmodnick)
181 { /* if H left the channel, we remove all the users from the channel */
182 while (hchan->channel_users)
183 {
184 huser_del_channel(hchan->channel_users->husr, hchan);
185 hchannel_del_user(hchan, hchan->channel_users->husr);
186 }
187 }
188
189 else if (handle_queue)
190 hqueue_handle_queue(hchan, oper);
191 }
192
193 static void helpmod_hook_nick_lostnick(int unused, void *args)
194 {
195 nick *nck = (nick*)args;
196 huser *husr = huser_get(nck);
197
198 /* it was someone we didn't even know */
199 if (husr == NULL)
200 return;
201
202 huser_del(husr);
203 }
204
205 static void helpmod_hook_channel_opped(int unused, void *args)
206 {
207 hchannel *hchan = hchannel_get_by_channel(((channel**)args)[0]);
208 huser_channel *huserchan;
209 huser *husr, *husr2;
210
211 if (hchan == NULL)
212 return;
213
214 husr = huser_get(((nick**)args)[2]);
215 husr2 = huser_get(((nick**)args)[1]);
216
217 assert(husr != NULL);
218
219 huserchan = huser_on_channel(husr, hchan);
220
221 assert(huserchan != NULL);
222
223 huserchan->flags |= HCUMODE_OP;
224
225 if (hchan->flags & H_PASSIVE)
226 return;
227
228 /* if the +o was given by a network service, G will not interfere */
229 if (husr2 == NULL || strlen(huser_get_nick(husr2)) == 1)
230 return;
231
232 if (huser_get_level(husr) < H_STAFF)
233 helpmod_channick_modes(husr, hchan, MC_DEOP ,HNOW);
234 }
235
236 static void helpmod_hook_channel_deopped(int unused, void *args)
237 {
238 hchannel *hchan = hchannel_get_by_channel(((channel**)args)[0]);
239 huser_channel *huserchan;
240 huser *husr;
241
242 if (hchan == NULL)
243 return;
244
245 husr = huser_get(((nick**)args)[2]);
246
247 assert(husr != NULL);
248
249 huserchan = huser_on_channel(husr, hchan);
250
251 assert(huserchan != NULL);
252
253 huserchan->flags &= ~HCUMODE_OP;
254 }
255
256 static void helpmod_hook_channel_voiced(int unused, void *args)
257 {
258 hchannel *hchan = hchannel_get_by_channel(((channel**)args)[0]);
259 huser_channel *huserchan;
260 huser *husr;
261
262 if (hchan == NULL)
263 return;
264 husr = huser_get(((nick**)args)[2]);
265
266 assert(husr != NULL);
267
268 huserchan = huser_on_channel(husr, hchan);
269
270 assert(huserchan != NULL);
271
272 huserchan->flags |= HCUMODE_VOICE;
273
274 if (hchan->flags & H_QUEUE)
275 {
276 huserchan->flags |= HQUEUE_DONE;
277 huserchan->last_activity = time(NULL);
278 }
279 }
280
281 static void helpmod_hook_channel_devoiced(int unused, void *args)
282 {
283 hchannel *hchan = hchannel_get_by_channel(((channel**)args)[0]);
284 huser_channel *huserchan;
285 huser *husr;
286
287 if (hchan == NULL)
288 return;
289
290 husr = huser_get(((nick**)args)[2]);
291
292 assert(husr != NULL);
293
294 huserchan = huser_on_channel(husr, hchan);
295
296 assert(huserchan != NULL);
297
298 huserchan->flags &= ~HCUMODE_VOICE;
299
300 if (hchan->flags & H_PASSIVE)
301 return;
302
303 if ((hchan->flags & H_QUEUE) && (hchan->flags & H_QUEUE_MAINTAIN) && (huser_get_level(husr) == H_PEON) && (huserchan->flags & HCUMODE_VOICE) && (hchannel_count_queue(hchan)))
304 {
305 if (serverlist[homeserver(husr->real_user->numeric)].linkstate != LS_SQUIT)
306 { /* if it was a netsplit, we do not trigger autoqueue */
307 hqueue_handle_queue(hchan, huserchan->responsible_oper);
308 }
309 }
310 }
311
312 static void helpmod_hook_channel_topic(int unused, void *args)
313 {
314 hchannel *hchan = hchannel_get_by_channel(((channel**)args)[0]);
315 huser *husr;
316
317 if (hchan == NULL || hchan->flags & H_PASSIVE)
318 return;
319
320 husr = huser_get(((nick**)args)[2]);
321
322 if (hchan->flags & H_HANDLE_TOPIC)
323 {
324 if (husr != NULL && huser_get_level(husr) >= H_OPER)
325 {
326 htopic_del_all(&hchan->topic);
327 htopic_add(&hchan->topic, hchan->real_channel->topic->content, 0);
328 }
329 else
330 {
331 hchannel_set_topic(hchan);
332 }
333 }
334 }
335
336 static void helpmod_hook_nick_account(int unused, void *args)
337 {
338 nick *nck = (nick*)args;
339 huser *husr = huser_get(nck);
340 huser_channel *huserchan, *huserchannext;
341 if (husr == NULL)
342 return;
343 else
344 husr->account = haccount_get_by_name(nck->authname);
345
346 if (huser_get_level(husr) == H_LAMER) {
347 for (huserchan = husr->hchannels; huserchan; huserchan = huserchannext) {
348 huserchannext = huserchan->next;
349 helpmod_kick(huserchan->hchan, husr, "Your presence on channel %s is not wanted", hchannel_get_name(huserchan->hchan));
350 }
351 }
352 }
353
354 static void helpmod_hook_server_newserver(int unused, void *args)
355 {
356 hchannel *hchan;
357 long numeric = (long)args;
358 server srv = serverlist[numeric];
359
360 /* check linkstate to prevent spam */
361 if (srv.linkstate == LS_LINKING)
362 {
363 for (hchan = hchannels;hchan != NULL;hchan = hchan->next)
364 if ((hchan->flags & H_HANDLE_TOPIC) && (hchan->topic != NULL))
365 hchannel_set_topic(hchan);
366 }
367 }
368
369 void helpmod_registerhooks(void)
370 {
371 /* registerhook(HOOK_NICK_QUIT, &helpmod_hook_quit); */
372 /*if (registerhook(HOOK_CHANNEL_PART, &helpmod_hook_part));*/
373 registerhook(HOOK_CHANNEL_JOIN, &helpmod_hook_join);
374 registerhook(HOOK_NICK_LOSTNICK, &helpmod_hook_nick_lostnick);
375 registerhook(HOOK_CHANNEL_NEWNICK, &helpmod_hook_channel_newnick);
376 registerhook(HOOK_CHANNEL_LOSTNICK, &helpmod_hook_channel_lostnick);
377 registerhook(HOOK_CHANNEL_OPPED, &helpmod_hook_channel_opped);
378 registerhook(HOOK_CHANNEL_DEOPPED, &helpmod_hook_channel_deopped);
379 registerhook(HOOK_CHANNEL_VOICED, &helpmod_hook_channel_voiced);
380 registerhook(HOOK_CHANNEL_DEVOICED, &helpmod_hook_channel_devoiced);
381 registerhook(HOOK_CHANNEL_TOPIC, &helpmod_hook_channel_topic);
382 registerhook(HOOK_NICK_ACCOUNT, &helpmod_hook_nick_account);
383 registerhook(HOOK_SERVER_NEWSERVER, &helpmod_hook_server_newserver);
384 }
385
386 void helpmod_deregisterhooks(void)
387 {
388 /* deregisterhook(HOOK_NICK_QUIT, &helpmod_hook_quit); */
389 /*if (deregisterhook(HOOK_CHANNEL_PART, &helpmod_hook_part));*/
390 deregisterhook(HOOK_CHANNEL_JOIN, &helpmod_hook_join);
391 deregisterhook(HOOK_NICK_LOSTNICK, &helpmod_hook_nick_lostnick);
392 deregisterhook(HOOK_CHANNEL_NEWNICK, &helpmod_hook_channel_newnick);
393 deregisterhook(HOOK_CHANNEL_LOSTNICK, &helpmod_hook_channel_lostnick);
394 deregisterhook(HOOK_CHANNEL_OPPED, &helpmod_hook_channel_opped);
395 deregisterhook(HOOK_CHANNEL_DEOPPED, &helpmod_hook_channel_deopped);
396 deregisterhook(HOOK_CHANNEL_VOICED, &helpmod_hook_channel_voiced);
397 deregisterhook(HOOK_CHANNEL_DEVOICED, &helpmod_hook_channel_devoiced);
398 deregisterhook(HOOK_CHANNEL_TOPIC, &helpmod_hook_channel_topic);
399 deregisterhook(HOOK_NICK_ACCOUNT, &helpmod_hook_nick_account);
400 deregisterhook(HOOK_SERVER_NEWSERVER, &helpmod_hook_server_newserver);
401 }