]> jfr.im git - irc/quakenet/newserv.git/blame - helpmod2/helpmod2.c
GLINES: fix null pointer deref in trustgline / trustungline
[irc/quakenet/newserv.git] / helpmod2 / helpmod2.c
CommitLineData
c86edd1d
Q
1#include <stdio.h>
2#include <string.h>
3#include <stdarg.h>
4#include <ctype.h>
5
c86edd1d
Q
6#include "helpmod_entries.h"
7#include "helpmod_alias.h"
8
9#include "helpmod.h"
10#include "hcommand.h"
11#include "hcommands.h"
12#include "hterm.h"
13#include "hchanban.h"
14#include "hcensor.h"
15#include "hchannel.h"
16#include "hlamer.h"
17#include "hban.h"
18#include "hconf.h"
19#include "hhooks.h"
20#include "hstat.h"
21#include "hgen.h"
22#include "hdef.h"
23#include "hticket.h"
9af95c3d 24#include "hed.h"
7f32dbdf
P
25#include "../lib/version.h"
26
27MODULE_VERSION("")
c86edd1d
Q
28
29int HELPMOD_ACCOUNT_EXPIRATION[] =
30{
31 14 * HDEF_d, /* H_LAMER */
e908ecfa 32 7 * HDEF_d, /* H_PEON */
052247fa 33 1 * HDEF_M, /* H_FRIEND */
e908ecfa 34 2 * HDEF_M, /* H_TRIAL */
35 6 * HDEF_M, /* H_STAFF */
36 1 * HDEF_y, /* H_OPER */
37 2 * HDEF_y /* H_ADMIN */
c86edd1d
Q
38};
39
40/* new H stuff */
41hcommand *hcommands;
42hchannel *hchannels;
43haccount *haccounts;
44hterm *hterms;
45hlc_profile *hlc_profiles;
46hban *hbans;
47huser *husers;
48hchanban *hchanbans;
9af95c3d 49helpmod_editor *helpmod_editors;
c86edd1d
Q
50
51modechanges hmodechanges;
52time_t helpmod_startup_time;
53
54helpmod_entry helpmod_base;
55alias_tree aliases;
56nick *helpmodnick;
57char helpmod_db[128] = "helpmod/default";
58long helpmod_usage;
59
60int hstat_cycle;
61time_t hstat_last_cycle;
62
63enum
64{
65 H_REPLY_PRIVMSG,
66 H_REPLY_NOTICE
67};
68
69void hcommit_modes(void)
70{
71 if (hmodechanges.cp == NULL)
72 return;
73 if (hchannel_get_by_channel(hmodechanges.cp)->flags & H_PASSIVE)
74 {
75 localsetmodeinit(&hmodechanges, NULL, helpmodnick);
76 return;
77 }
78 localsetmodeflush(&hmodechanges, 1);
79 localsetmodeinit(&hmodechanges, NULL, helpmodnick);
80}
81
82void helpmod_reply(huser *target, channel* returntype, const char *message, ... )
83{
84 char buf[512];
85 va_list va;
86 int reply_type;
87
88 if (helpmodnick==NULL) {
89 return;
90 }
91
92 va_start(va,message);
93 vsnprintf(buf,512,message,va);
94 va_end(va);
95
9af95c3d 96 if (buf[0] == '\0' || buf[0] == '\n')
97 return;
98
c86edd1d
Q
99 if (returntype) /* channel */
100 reply_type = H_REPLY_NOTICE;
101 else /* private */
102 reply_type = H_REPLY_PRIVMSG;
103
104 if (target->account != NULL)
105 {
106 if (target->account->flags & H_ALL_PRIVMSG)
107 reply_type = H_REPLY_PRIVMSG;
108 if (target->account->flags & H_ALL_NOTICE)
109 reply_type = H_REPLY_NOTICE;
110 }
111
112 if (reply_type == H_REPLY_PRIVMSG)
113 sendmessagetouser(helpmodnick,target->real_user, "%s", buf);
114 else
115 sendnoticetouser(helpmodnick,target->real_user, "%s", buf);
116}
117
118void helpmod_message_channel(hchannel *hchan, const char *message, ...)
119{
120 char buf[512];
121 va_list va;
122
123 if (helpmodnick==NULL || hchan == NULL) {
124 return;
125 }
126
127 va_start(va,message);
128 vsnprintf(buf,512,message,va);
129 va_end(va);
130
e908ecfa 131 if (hchan->flags & H_PASSIVE)
132 return;
133
b808acb7 134 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", buf);
c86edd1d
Q
135}
136
137void helpmod_message_channel_long(hchannel *hchan, const char *message, ...)
138{
139 char buf[2048], *bp = buf;
140 va_list va;
141 int i;
142
143 if (helpmodnick==NULL || hchan == NULL) {
144 return;
145 }
146
147 va_start(va,message);
148 vsnprintf(buf,2048,message,va);
149 va_end(va);
150
e908ecfa 151 if (hchan->flags & H_PASSIVE)
152 return;
153
c86edd1d
Q
154 while (strlen(bp) > 450)
155 {
156 for (i=0;i<50;i++)
157 if (isspace(bp[390 + i]))
158 {
159 bp[390 + i] = '\0';
160 break;
161 }
162 if (i == 50)
163 bp[390 + i] = '\0';
b808acb7 164 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", bp);
c86edd1d
Q
165 bp+=(390+i+1);
166 }
167 if (*bp)
b808acb7 168 sendmessagetochannel(helpmodnick, hchan->real_channel, "%s", bp);
c86edd1d
Q
169}
170
171void helpmod_kick(hchannel *hchan, huser *target, const char *reason, ...)
172{
173 char buf[512];
174 va_list va;
175
176 if (hchan->flags & H_PASSIVE)
177 return;
178
179 va_start(va,reason);
180 vsnprintf(buf,512,reason,va);
181 va_end(va);
182
183 localkickuser(helpmodnick, hchan->real_channel, target->real_user, buf);
184}
185
186void helpmod_invite(hchannel *hchan, huser *husr)
187{
e908ecfa 188 if (hchan->flags & H_PASSIVE)
189 return;
190
620cc49d 191 localinvite(helpmodnick, hchan->real_channel->index, husr->real_user);
c86edd1d
Q
192}
193
194static void hmode_set_channel(hchannel *hchan)
195{
196 if (hmodechanges.cp && hmodechanges.cp != hchan->real_channel)
197 hcommit_modes();
198 hmodechanges.cp = hchan->real_channel;
199}
200
201void helpmod_channick_modes(huser *target, hchannel *hchan, short mode, int now)
202{
203 void *args[] = { hchan->real_channel, helpmodnick, target->real_user};
204 hmode_set_channel(hchan);
205 localdosetmode_nick(&hmodechanges, target->real_user, mode);
206
207 if (huser_on_channel(target, hchan) == NULL)
208 {
3a839281 209 Error("helpmod", ERR_WARNING, "Channick mode for user %s not on channel %s", huser_get_nick(target), hchannel_get_name(hchan));
c86edd1d
Q
210 return;
211 }
212
e908ecfa 213 if (hchan->flags & H_PASSIVE)
214 return;
215
c86edd1d
Q
216 switch (mode)
217 {
218 case MC_OP:
219 triggerhook(HOOK_CHANNEL_OPPED, args);
220 break;
221 case MC_DEOP:
222 triggerhook(HOOK_CHANNEL_DEOPPED, args);
223 break;
224 case MC_VOICE:
225 triggerhook(HOOK_CHANNEL_VOICED, args);
226 break;
227 case MC_DEVOICE:
228 triggerhook(HOOK_CHANNEL_DEVOICED, args);
229 break;
230 }
231
232 if (now)
233 hcommit_modes();
234}
235
236void helpmod_setban(hchannel *hchan, const char *banstr, time_t expiration, int type, int now)
237{
238 hmode_set_channel(hchan);
e908ecfa 239
240 if (hchan->flags & H_PASSIVE)
241 return;
242
c86edd1d
Q
243 localdosetmode_ban(&hmodechanges, banstr, type);
244
245 if ((type == MCB_ADD) && (expiration > time(NULL)))
246 scheduleoneshot(expiration, (ScheduleCallback)&hchanban_schedule_entry, hchanban_add(hchan, banstr, expiration));
247
248 if (now)
249 hcommit_modes();
250}
251
252void helpmod_simple_modes(hchannel *hchan, int add, int remove, int now)
253{
254 hmode_set_channel(hchan);
255
e908ecfa 256 if (hchan->flags & H_PASSIVE)
257 return;
258
c86edd1d
Q
259 localdosetmode_simple(&hmodechanges, add, remove);
260
261 if (now)
262 hcommit_modes();
263}
264
265void helpmod_set_topic(hchannel *hchan, const char* topic)
266{
e908ecfa 267 if (hchan->flags & H_PASSIVE)
268 return;
269
c86edd1d
Q
270 localsettopic(helpmodnick, hchan->real_channel, (char*)topic);
271}
272
273void helpmod_privmsg(void **args)
274{
275 void *sender = args[0];
276 void *message = args[1];
277
278 nick *sender_nick;
279 huser *sender_huser;
280
281 sender_nick = getnickbynick((char*)sender);
282
283 if ((sender_huser = huser_get(sender_nick)) == NULL)
284 sender_huser = huser_add(sender_nick);
285
286 huser_activity(sender_huser, NULL);
287
288 helpmod_command(sender_huser, NULL, (char*)message);
289}
290
291void helpmod_chan_privmsg(void **args)
292{
293 void *sender = args[0];
294 channel *chan = (channel*)args[1];
295 void *message = args[2];
296
297 nick *sender_nick;
298 huser *sender_huser;
299 hcensor *tmp;
300 hchannel *hchan = hchannel_get_by_channel(chan);
301
302 sender_nick = getnickbynick((char*)sender);
303
304 if ((hchan == NULL || hchan->flags & H_PASSIVE))
305 return;
306
307 if ((sender_huser = huser_get(sender_nick)) == NULL)
308 sender_huser = huser_add(sender_nick);
309
310 if (hchan->flags & H_DO_STATS)
3a839281 311 {
312 if (sender_huser->account != NULL)
313 hstat_calculate_account(hchan, sender_huser, message);
314 hstat_calculate_channel(hchan, sender_huser, message);
315 }
c86edd1d
Q
316 huser_activity(sender_huser, hchan);
317
e5882ade 318 if (huser_get_level(sender_huser) < H_FRIEND) /* staff, staff trials and friends are not subject to any control */
c86edd1d
Q
319 {
320 if ((hchan->flags & H_CENSOR) && (tmp = hcensor_check(hchan->censor, (char*)message)))
321 { /* censor match */
643deb1b 322 if (hcensor_match(hchan, sender_huser, tmp))
323 return;
c86edd1d
Q
324 }
325 if ((hchan->flags & H_LAMER_CONTROL) && (hlc_check(hchan, sender_huser, (char*)message)))
326 return;
327 if ((hchan->flags & H_DISALLOW_LAME_TEXT) && helpmod_is_lame_line(message))
328 {
3a839281 329 helpmod_kick(hchan, sender_huser, "Please only use normal text on %s", hchannel_get_name(hchan));
c86edd1d 330 return;
135d6084 331 }
332 if ((hchan->flags & H_HIGHLIGHT_PREVENTION) && hchannel_highlight_detection(hchan, (char*)message))
333 {
334 helpmod_kick(hchan, sender_huser, "Please do not abuse the highlight feature of IRC clients");
335 return;
336 }
c86edd1d
Q
337 }
338
339 if (hcommand_is_command((char*)message) && (hchan->flags & H_CHANNEL_COMMANDS))
340 helpmod_command(sender_huser, chan, (char*)message);
341}
342
343void helpmod_kicked(void **args)
344{
345 /* just rejoin the channel, if an oper wants H gone he can use delchan */
346 channel *cp = findchannel(args[1]);
347 if (!cp)
348 localcreatechannel(helpmodnick, args[1]);
349 else
350 {
351 localjoinchannel(helpmodnick, cp);
352 localgetops(helpmodnick, cp);
353 }
354}
355
356void helpmodmessagehandler(nick *sender, int messagetype, void **args)
357{
358 switch (messagetype)
359 {
360 case LU_PRIVMSG:
361 helpmod_privmsg(args);
362 break;
363 case LU_CHANMSG:
364 helpmod_chan_privmsg(args);
365 break;
366 case LU_KICKED:
367 helpmod_kicked(args);
368 break;
369 }
370
371 hcommit_modes();
372}
373
374void helpconnect(void) {
375 /* register H */
376 helpmodnick=registerlocaluser(HELPMOD_NICK,
377 "help",
378 "quakenet.org",
b808acb7 379 "NewServ HelpMod 2, /msg "HELPMOD_NICK" help",
c86edd1d
Q
380 HELPMOD_AUTH,
381 UMODE_OPER|UMODE_ACCOUNT|UMODE_SERVICE,&helpmodmessagehandler);
382 /* register hooks */
383 helpmod_registerhooks();
384
385 /* continue with the database */
386 if (helpmod_config_read(HELPMOD_DEFAULT_DB))
387 {
388 Error("helpmod", ERR_WARNING, "Error reading the default database '%s'", HELPMOD_DEFAULT_DB);
389 if (helpmod_config_read(HELPMOD_FALLBACK_DB))
390 Error("helpmod", ERR_ERROR, "Error reading the fallback database '%s'", HELPMOD_FALLBACK_DB);
391 }
392 if (!haccounts)
393 Error("helpmod", ERR_ERROR, "Read 0 accounts from database (something is broken)");
394
395 /* old H */
396 helpmod_init_entry(&helpmod_base);
397 helpmod_load_entries(HELPMOD_HELP_DEFAULT_DB);
398}
399
400void _init()
401{
402 helpmod_usage = 0;
403 helpmod_base = NULL;
404 aliases = NULL;
405
406 hcommands = NULL;
407 hchannels = NULL;
408 hlc_profiles = NULL;
409 husers = NULL;
410 haccounts = NULL;
411 hbans = NULL;
412 hterms = NULL;
413 hchanbans = NULL;
414
415 helpmod_startup_time = time(NULL);
416 /* add the supported commands, needs to be done like this since 3 arrays would just become a mess */
417 /* first the legacy old-H commands */
418
419 hcommands_add();
420
421 srand(time(NULL));
422
423 /* init hmodechanges */
424 localsetmodeinit(&hmodechanges, NULL, helpmodnick);
425
426 schedulerecurring(time(NULL)+1,0,HDEF_h,(ScheduleCallback)&huser_clear_inactives,NULL);
427 schedulerecurring(time(NULL)+1,0,HDEF_d,(ScheduleCallback)&haccount_clear_inactives,NULL);
428 schedulerecurring(time(NULL)+1,0,HDEF_m,(ScheduleCallback)&hban_remove_expired,NULL);
af204779 429 /* disable idle kick - meeb 2017-03-22
430 schedulerecurring(time(NULL)+1,0,30 * HDEF_s, (ScheduleCallback)&hchannel_remove_inactive_users, NULL); */
e908ecfa 431 schedulerecurring(time(NULL)+1,0,60 * HDEF_m,(ScheduleCallback)&hchannel_report, NULL);
c86edd1d
Q
432 schedulerecurring(time(NULL) + HDEF_h, 0, 6 * HDEF_h, (ScheduleCallback)&helpmod_config_scheduled_events, NULL);
433 schedulerecurring(time(NULL)+1,0,10 * HDEF_m, (ScheduleCallback)&hticket_remove_expired, NULL);
434 schedulerecurring(hstat_get_schedule_time() - 5 * HDEF_m, 0, HDEF_d, (ScheduleCallback)&hstat_scheduler, NULL);
435
436 helpconnect();
437}
438
439void _fini()
440{
441 helpmod_deregisterhooks();
442 /* write the database so that we don't lose anything
443 existance of atleast one account is required (sanity check)
444 */
445 if (haccounts)
446 helpmod_config_write(HELPMOD_DEFAULT_DB);
447
448 /* delete schedule stuff */
449 deleteallschedules((ScheduleCallback)&helpconnect);
450 deleteallschedules((ScheduleCallback)&huser_clear_inactives);
451 deleteallschedules((ScheduleCallback)&haccount_clear_inactives);
452 deleteallschedules((ScheduleCallback)&hban_remove_expired);
af204779 453 /* disable idle kick - meeb 2017-03-22
454 deleteallschedules((ScheduleCallback)&hchannel_remove_inactive_users); */
c86edd1d
Q
455 deleteallschedules((ScheduleCallback)&hchannel_report);
456 deleteallschedules((ScheduleCallback)&helpmod_config_scheduled_events);
457 deleteallschedules((ScheduleCallback)&hstat_scheduler);
458 deleteallschedules((ScheduleCallback)&hchannel_deactivate_join_flood);
459 deleteallschedules((ScheduleCallback)&hchanban_schedule_entry);
460 deleteallschedules((ScheduleCallback)&hticket_remove_expired);
461
462 hcommand_del_all();
463 hchannel_del_all();
464 huser_del_all();
465 hlc_del_all();
466 hban_del_all();
467 hterm_del_all(NULL);
468 hchanban_del_all();
469 helpmod_clear_aliases(&aliases);
470 helpmod_clear_all_entries();
471
472 deregisterlocaluser(helpmodnick, "Module unloaded");
473}