]> jfr.im git - irc/quakenet/newserv.git/blame - helpmod2/hchannel.c
GLINES: fix null pointer deref in trustgline / trustungline
[irc/quakenet/newserv.git] / helpmod2 / hchannel.c
CommitLineData
c86edd1d
Q
1
2#include <stdlib.h>
3#include <assert.h>
135d6084 4#include <string.h>
5#include <ctype.h>
c86edd1d 6
c86edd1d
Q
7#include "hchannel.h"
8#include "haccount.h"
9#include "helpmod.h"
10#include "hqueue.h"
11#include "hgen.h"
12#include "hchanban.h"
13#include "hban.h"
14
15hchannel *hchannel_add(const char *cname)
16{
17 channel *cp;
18 hchannel *hchan;
19
20 cp = findchannel((char*)cname);
21 if (!cp)
22 {
23 localcreatechannel(helpmodnick, (char*)cname);
24 cp = findchannel((char*)cname);
25 }
26 else
27 {
28 localjoinchannel(helpmodnick, cp);
29 localgetops(helpmodnick, cp);
30 }
31
32 hchan = (hchannel*)malloc(sizeof(hchannel));
33
34 hchan->welcome[0] = '\0';
35 hchan->real_channel = cp;
36 hchan->flags = H_CHANFLAGS_DEFAULT;
37 hchan->channel_users = NULL;
38 hchan->channel_hterms = NULL;
39 hchan->max_idle = 5 * HDEF_m;
40 hchan->topic = NULL;
41 hchan->report_to = NULL;
42
43 hchan->autoqueue = 0;
44 hchan->jf_control = time(NULL);
45 hchan->lc_profile = NULL;
46 hchan->censor = NULL;
47
48 hchan->htickets = NULL;
9af95c3d 49 hchan->ticket_message = NULL;
c86edd1d 50
3a839281 51 hchan->last_activity = time(NULL);
52 hchan->last_staff_activity = time(NULL);
c86edd1d
Q
53 hchan->stats = get_hstat_channel();
54
55 hchan->next = hchannels;
56 hchannels = hchan;
57
58 {
59 int i;
60 nick *nck;
61 huser *husr;
62 huser_channel *tmp;
63 for (i=0;i < hchan->real_channel->users->hashsize;i++)
64 {
65 nck = getnickbynumeric(hchan->real_channel->users->content[i]);
66 if (!nck) /* it's a hash, not an array */
67 continue;
68
69 if ((husr = huser_get(nck)) == NULL)
70 husr = huser_add(nck);
3a839281 71
72 tmp = huser_add_channel(husr, hchan);
c86edd1d
Q
73 hchannel_add_user(hchan, husr);
74
75 if (hchan->real_channel->users->content[i] & CUMODE_OP)
76 tmp->flags |= HCUMODE_OP;
77 if (hchan->real_channel->users->content[i] & CUMODE_VOICE)
78 tmp->flags |= HCUMODE_VOICE;
79 }
80 }
81 return hchan;
82}
83
84int hchannel_del(hchannel *hchan)
85{
86 hchannel *tmp, **ptr = &hchannels;
87
88 for (;*ptr;ptr = &(*ptr)->next)
89 if (*ptr == hchan)
90 break;
91
92 assert(*ptr != NULL);
93
94 tmp = hchan->next;
95
96 hcensor_del_all(&(hchan->censor));
97 hterm_del_all(&hchan->channel_hterms);
98 htopic_del_all(&hchan->topic);
99 hstat_del_channel(hchan);
100 free(hchan->stats);
101
102 while (hchan->htickets)
103 hticket_del(hchan->htickets, hchan);
104
334b567e 105 localpartchannel(helpmodnick, hchan->real_channel, "Channel Removed");
c86edd1d
Q
106
107 free(hchan);
108
109 *ptr = tmp;
110
111 return 0;
112}
113
114int hchannel_authority(hchannel *hchan, struct huser_struct *husr)
115{
116 if ((hchan->flags & H_OPER_ONLY) && (huser_get_level(husr) < H_OPER))
117 return 0;
118 return 1;
119}
120
121hchannel *hchannel_get_by_name(const char *cname)
122{
123 hchannel *tmp = hchannels;
124 for (;tmp;tmp=tmp->next)
125 if (!ircd_strcmp(cname, tmp->real_channel->index->name->content))
126 return tmp;
127 return NULL;
128}
129
130hchannel *hchannel_get_by_channel(channel *chan)
131{
132 hchannel *tmp;
133
134 if (chan == NULL)
135 return NULL;
136
137 tmp = hchannels;
138 for (;tmp;tmp=tmp->next)
139 if (tmp->real_channel == chan)
140 return tmp;
141 return NULL;
142}
143
c86edd1d
Q
144const char *hchannel_get_name(hchannel *hchan)
145{
146 return hchan->real_channel->index->name->content;
147}
148
149void hchannel_del_all(void)
150{
151 while (hchannels)
152 hchannel_del(hchannels);
153}
154
155hchannel_user *hchannel_on_channel(hchannel *hchan, struct huser_struct *husr)
156{
157 hchannel_user *ptr = hchan->channel_users;
158 for (;ptr;ptr = ptr->next)
159 if (ptr->husr == husr)
160 return ptr;
161 return NULL;
162}
163
164hchannel_user *hchannel_add_user(hchannel *hchan, struct huser_struct *husr)
165{
166 hchannel_user **tmp = &(hchan->channel_users);
167 assert(hchannel_on_channel(hchan, husr) == NULL);
168
169 for (;*tmp;tmp = &(*tmp)->next);
170
171 *tmp = (hchannel_user*)malloc(sizeof(hchannel_user));
172 (*tmp)->husr = husr;
173 (*tmp)->time_joined = time(NULL);
174 (*tmp)->next = NULL;
175
176 assert(hchannel_on_channel(hchan, husr) != NULL);
177
178 return *tmp;
179}
180
181hchannel_user *hchannel_del_user(hchannel *hchan, struct huser_struct *husr)
182{
183 hchannel_user **tmp = &(hchan->channel_users);
184 assert(hchannel_on_channel(hchan, husr) != NULL);
185
186 for (;*tmp;tmp = &(*tmp)->next)
187 if ((*tmp)->husr == husr)
188 {
189 hchannel_user *ptr = (*tmp)->next;
190 free(*tmp);
191 *tmp = ptr;
192
193 assert(hchannel_on_channel(hchan, husr) == NULL);
194 return NULL;
195 }
196 return NULL;
197}
198
199void hchannel_remove_inactive_users(void)
200{
201 hchannel *hchan = hchannels;
202
203 for (;hchan;hchan = hchan->next)
204 {
205 if (hchan->flags & H_ANTI_IDLE && !(hchan->flags & H_PASSIVE))
206 {
207 hchannel_user **hchanuser = &hchan->channel_users;
208 while (*hchanuser)
209 {
ce659137 210 if (
211 (huser_get_level((*hchanuser)->husr) == H_PEON) &&
212 (time(NULL) - huser_on_channel((*hchanuser)->husr,hchan)->last_activity >= hchan->max_idle) &&
056e1ea4 213 !(on_queue((*hchanuser)->husr, huser_on_channel((*hchanuser)->husr, hchan)))
ce659137 214 )
215 {
216 if (huser_on_channel((*hchanuser)->husr, hchan)->flags & H_IDLE_WARNING)
c86edd1d 217 {
b808acb7 218 const char *banmask = hban_ban_string((*hchanuser)->husr->real_user, HBAN_HOST);
f1cc5921
CP
219 int bantime = 10;
220 helpmod_setban(hchan, banmask, time(NULL) + bantime * HDEF_m, MCB_ADD, HLAZY);
c86edd1d 221
f1cc5921 222 helpmod_kick(hchan, (*hchanuser)->husr, "Please do not idle in %s (%dmin anti-idle tempban). If you still require assistance, please try again later.", hchannel_get_name(hchan), bantime);
c86edd1d
Q
223 continue;
224 }
225 else
226 {
227 helpmod_reply((*hchanuser)->husr, NULL, "You are currently idle in %s. Please part the channel if you have nothing to do there", hchannel_get_name(hchan));
228 huser_on_channel((*hchanuser)->husr, hchan)->flags |= H_IDLE_WARNING;
9af95c3d 229 }
230 }
9f824c95 231 /*hcommit_modes();*/
c86edd1d 232 hchanuser = &(*hchanuser)->next;
9f824c95 233 }
234 hcommit_modes();
c86edd1d
Q
235 }
236 /* Additionally, test if the channel has queue but no idle opers / staff */
237 if (hchan->flags & H_QUEUE && hchan->flags & H_QUEUE_TIMEOUT)
238 {
239 hchannel_user *tmp;
240 for (tmp = hchan->channel_users;tmp;tmp = tmp->next)
052247fa 241 if (huser_get_level(tmp->husr) >= H_TRIAL)
c86edd1d
Q
242 {
243 huser_channel *huserchan = huser_on_channel(tmp->husr, hchan);
244 if ((time(NULL) - huserchan->last_activity < HELPMOD_QUEUE_TIMEOUT) && (huserchan->last_activity != tmp->time_joined))
245 break;
246 }
247 if (!tmp)
248 {
249 hchan->flags &= ~H_QUEUE;
250 if (hchan->flags & H_REPORT && hchannel_is_valid(hchan->report_to))
251 helpmod_message_channel(hchan->report_to, "%s: Channel queue deactivated because of inactivity", hchannel_get_name(hchan));
252 hchannel_conf_change(hchan, hchan->flags | H_QUEUE);
253 }
254 }
255 }
256}
257
258void hchannel_report(void)
259{
260 hchannel *hchan = hchannels;
261 for (;hchan;hchan = hchan->next)
262 if (hchan->flags & H_REPORT && !(hchan->flags & H_PASSIVE) && hchannel_is_valid(hchan->report_to))
263 {
264 int total = hchannel_count_users(hchan, H_ANY);
265 int peons = hchannel_count_users(hchan, H_PEON);
266 int services = hchannel_count_users(hchan, H_SERVICE);
267
268 if (peons == 0)
269 return;
270
271 if (hchan->flags & H_QUEUE)
272 {
273 int peons_queue = hchannel_count_queue(hchan);
274 helpmod_message_channel(hchan->report_to, "%s: %d user%s in queue and %d user%s currently receiving support. %d Non-user%s. Average queue time %s", hchannel_get_name(hchan), peons_queue, (peons_queue==1)?"":"s", peons - peons_queue, (peons - peons_queue == 1)?"":"s", total-peons-services, (total-peons-services == 1)?"":"s", helpmod_strtime(hqueue_average_time(hchan)));
275 }
276 else
277 helpmod_message_channel(hchan->report_to, "%s: %d user%s and %d non-user%s", hchannel_get_name(hchan), peons, (peons == 1)?"":"s", total-peons-services, (total-peons-services == 1)?"":"s");
278 }
279}
280
281void hchannel_set_topic(hchannel *hchan)
282{
283 if (hchan->flags & H_HANDLE_TOPIC)
284 helpmod_set_topic(hchan, htopic_construct(hchan->topic));
285}
286
287void hchannels_match_accounts(void)
288{
289 hchannel *hchan = hchannels;
290 hchannel_user *hchanuser;
291 for (;hchan;hchan = hchan->next)
292 for (hchanuser = hchan->channel_users;hchanuser;hchanuser = hchanuser->next)
293 if (hchanuser->husr->account == NULL && IsAccount(hchanuser->husr->real_user))
3a839281 294 hchanuser->husr->account = haccount_get_by_name(huser_get_auth(hchanuser->husr));
c86edd1d
Q
295}
296
297int hchannels_on_queue(huser *husr)
298{
299 huser_channel *huserchan = husr->hchannels;
300 for (;huserchan;huserchan = huserchan->next)
301 if (on_queue(husr, huserchan))
302 return 1;
303 return 0;
304}
305
306int hchannels_on_desk(struct huser_struct* husr)
307{
308 huser_channel *huserchan = husr->hchannels;
309 for (;huserchan;huserchan = huserchan->next)
310 if (on_desk(husr, huserchan))
311 return 1;
312 return 0;
313}
314
315void hchannels_dnmo(struct huser_struct *husr)
316{
317 hchannel *hchan = hchannels;
318 for (;hchan;hchan = hchan->next)
319 {
320 huser_channel *huserchan = huser_on_channel(husr, hchan);
321 /*if (on_queue(husr, huserchan) || on_desk(husr, huserchan))*/
322 if (huserchan != NULL)
323 {
f011b15a 324 hchannel_user *tmp = NULL, **hchanuser = &hchan->channel_users;
c86edd1d
Q
325 for (;*hchanuser;hchanuser = &(*hchanuser)->next)
326 if ((*hchanuser)->husr == husr)
327 {
328 tmp = *hchanuser;
329 *hchanuser = (*hchanuser)->next;
330 if (!*hchanuser)
331 break;
332 }
333 *hchanuser = tmp;
7d54716c 334 assert(*hchanuser != NULL);
c86edd1d
Q
335 (*hchanuser)->next = NULL;
336 if (on_desk(husr, huserchan))
337 {
338 helpmod_channick_modes(husr, hchan, MC_DEVOICE, HLAZY);
339 huserchan->flags &= ~HQUEUE_DONE;
340 }
341 }
342 }
343}
344
345int hchannel_count_users(hchannel *hchan, hlevel lvl)
346{
347 int count = 0;
348 hchannel_user *hchanuser = hchan->channel_users;
349 for (;hchanuser;hchanuser = hchanuser->next)
350 if (lvl == H_ANY)
351 count++;
352 else if (huser_get_level(hchanuser->husr) == lvl)
353 count++;
354 return count;
355}
356
357int hchannel_count_queue(hchannel *hchan)
358{
359 int count = 0;
360 hchannel_user *hchanuser = hchan->channel_users;
361 for (;hchanuser;hchanuser = hchanuser->next)
362 {
363 if (on_queue(hchanuser->husr, huser_on_channel(hchanuser->husr, hchan)))
364 count++;
365 }
366 return count;
367}
368
369int hchannel_is_valid(hchannel *hchan)
370{
371 hchannel *ptr = hchannels;
372 for (;ptr;ptr = ptr->next)
373 if (hchan == ptr)
374 return 1;
375 return 0;
376}
377
378void hchannel_mode_check(hchannel *hchan)
379{
380 if (((hchan->flags & H_MAINTAIN_M) || (hchan->flags & H_QUEUE)) && !IsModerated(hchan->real_channel))
381 helpmod_simple_modes(hchan, CHANMODE_MODERATE, 0,0);
382 else if (!((hchan->flags & H_MAINTAIN_M) || (hchan->flags & H_QUEUE)) && IsModerated(hchan->real_channel))
383 helpmod_simple_modes(hchan, 0, CHANMODE_MODERATE ,0);
384 if (hchan->flags & H_MAINTAIN_I && !IsInviteOnly(hchan->real_channel))
385 helpmod_simple_modes(hchan, CHANMODE_INVITEONLY, 0,0);
386 else if (!(hchan->flags & H_MAINTAIN_I) && IsInviteOnly(hchan->real_channel))
387 helpmod_simple_modes(hchan, 0, CHANMODE_INVITEONLY, 0);
388}
389
390void hchannel_conf_change(hchannel *hchan, int old_flags)
391{
392 int i;
393 hflagchange change;
394
395 for (i=0;i<HCHANNEL_CONF_COUNT;i++)
396 {
397 if ((hchan->flags ^ old_flags) & (1 << i))
398 {
399 change = (hchan->flags & (1 << i))?H_ON:H_OFF;
400 switch (1 << i)
401 {
402 case H_QUEUE:
403 hchannel_mode_check(hchan);
404 if (change == H_ON)
405 helpmod_message_channel(hchan, "Channel queue has been activated, all users enqueued");
406 else
407 helpmod_message_channel(hchan, "Channel queue has been deactivated");
408 break;
409 case H_MAINTAIN_I:
410 case H_MAINTAIN_M:
411 hchannel_mode_check(hchan);
412 break;
413 }
414 }
415 }
416}
417
418int hchannel_count(void)
419{
420 hchannel *hchan = hchannels;
421 int count = 0;
422 for (;hchan;hchan = hchan->next)
423 count++;
424 return count;
425}
426
427void hchannel_activate_join_flood(hchannel *hchan)
428{
429 hchannel_user **hchanuser = &hchan->channel_users;
430 helpmod_simple_modes(hchan, CHANMODE_REGONLY, 0, 1);
431
432 /* clean the channel of the already joined clients */
433 while (*hchanuser)
434 if (((*hchanuser)->time_joined > (time(NULL) - 5)) && huser_get_level((*hchanuser)->husr) < H_STAFF)
435 helpmod_kick(hchan, (*hchanuser)->husr, "Join flood");
436 else
437 hchanuser = &(*hchanuser)->next;
438
439 hchan->flags |= H_JOIN_FLOOD;
440
441 scheduleoneshot(time(NULL) + 60, &hchannel_deactivate_join_flood, NULL);
442}
e908ecfa 443
c86edd1d
Q
444/* goes to schedule */
445void hchannel_deactivate_join_flood()
446{
447 hchannel *hchan = hchannels;
448 for (;hchan;hchan = hchan->next)
449 if (hchan->flags & H_JOIN_FLOOD)
450 {
451 helpmod_simple_modes(hchan, 0, CHANMODE_REGONLY, 1);
452 hchan->flags &= ~H_JOIN_FLOOD;
453 }
c86edd1d
Q
454}
455
3a839281 456const char *hchannel_get_state(hchannel* hchan, int mask)
457{
458 if (hchan->flags & mask)
459 return "Yes";
460 else
461 return "No";
462}
463
135d6084 464int hchannel_highlight_detection(hchannel *hchan, const char *message)
465{
466 char buffer[512], *buffer_ptr = buffer, *ptr = buffer;
052247fa 467 int i, matches = 0;
135d6084 468
469 strcpy(buffer, message);
470
052247fa
CP
471 /* remove commas */
472 for (i=0;i<512 && buffer[i] != '\0';i++)
473 if (buffer[i] == ',')
474 buffer[i] = ' ';
475
476 /* reset i for loop */
477 i = 0;
135d6084 478 do
479 {
480 nick *tmp;
481 huser *tmp_huser;
482 huser_channel *tmp_huserchan;
483
484 if (i++ > 6)
485 break;
486
9f824c95 487 while (*buffer_ptr && isspace(*buffer_ptr))
135d6084 488 buffer_ptr++;
489
9f824c95 490 if (*buffer_ptr == '@')
491 buffer_ptr++;
492
135d6084 493 if (*buffer_ptr)
494 {
495 ptr = strchr(buffer_ptr, ' ');
496 if (ptr)
497 {
498 *ptr = '\0';
499 ptr++;
500 }
501 if ((tmp = getnickbynick(buffer_ptr)))
502 if ((tmp_huser = huser_get(tmp)))
503 if ((tmp_huserchan = huser_on_channel(tmp_huser, hchan)))
504 if ((tmp_huserchan->flags & HCUMODE_OP) && strlen(huser_get_nick(tmp_huser)) > 1)
505 matches++;
506 }
507 if (ptr == NULL)
508 break;
509 else
510 buffer_ptr = ptr;
511 } while (*ptr);
512
513 if (matches > 2)
514 return 1;
515 else
516 return 0;
517}
3a839281 518
c86edd1d
Q
519const char *hchannel_get_sname(int flag)
520{
521 if (flag < 0 || flag > HCHANNEL_CONF_COUNT)
522 return NULL;
523
524 switch (flag)
525 {
526 case 0:
527 return "Passive state";
528 case 1:
529 return "Welcome message";
530 case 2:
531 return "JoinFlood protection";
532 case 3:
533 return "Queue";
534 case 4:
535 return "Verbose queue (requires queue)";
536 case 5:
537 return "Auto queue (requires queue)";
538 case 6:
539 return "Channel status reporting";
540 case 7:
541 return "Pattern censor";
542 case 8:
543 return "Lamer control";
544 case 9:
545 return "Idle user removal";
546 case 10:
547 return "Keep channel moderated";
548 case 11:
549 return "Keep channel invite only";
550 case 12:
551 return "Handle channel topic";
552 case 13:
553 return "Calculate statistic";
554 case 14:
555 return "Remove joining trojans";
556 case 15:
557 return "Channel commands";
558 case 16:
559 return "Oper only channel";
560 case 17:
561 return "Disallow bold, underline, etc.";
562 case 18:
563 return "Queue inactivity deactivation";
564 case 19:
9af95c3d 565 return "Require a ticket to join";
566 case 20:
135d6084 567 return "Send a message on ticket issue";
568 case 21:
569 return "Excessive highlight prevention";
c86edd1d 570 default:
e908ecfa 571 return "Error, please contact strutsi";
c86edd1d
Q
572 }
573}