]> jfr.im git - irc/quakenet/newserv.git/blob - helpmod2/hchannel.c
GLINES: fix null pointer deref in trustgline / trustungline
[irc/quakenet/newserv.git] / helpmod2 / hchannel.c
1
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <ctype.h>
6
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
15 hchannel *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;
49 hchan->ticket_message = NULL;
50
51 hchan->last_activity = time(NULL);
52 hchan->last_staff_activity = time(NULL);
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);
71
72 tmp = huser_add_channel(husr, hchan);
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
84 int 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
105 localpartchannel(helpmodnick, hchan->real_channel, "Channel Removed");
106
107 free(hchan);
108
109 *ptr = tmp;
110
111 return 0;
112 }
113
114 int 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
121 hchannel *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
130 hchannel *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
144 const char *hchannel_get_name(hchannel *hchan)
145 {
146 return hchan->real_channel->index->name->content;
147 }
148
149 void hchannel_del_all(void)
150 {
151 while (hchannels)
152 hchannel_del(hchannels);
153 }
154
155 hchannel_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
164 hchannel_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
181 hchannel_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
199 void 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 {
210 if (
211 (huser_get_level((*hchanuser)->husr) == H_PEON) &&
212 (time(NULL) - huser_on_channel((*hchanuser)->husr,hchan)->last_activity >= hchan->max_idle) &&
213 !(on_queue((*hchanuser)->husr, huser_on_channel((*hchanuser)->husr, hchan)))
214 )
215 {
216 if (huser_on_channel((*hchanuser)->husr, hchan)->flags & H_IDLE_WARNING)
217 {
218 const char *banmask = hban_ban_string((*hchanuser)->husr->real_user, HBAN_HOST);
219 int bantime = 10;
220 helpmod_setban(hchan, banmask, time(NULL) + bantime * HDEF_m, MCB_ADD, HLAZY);
221
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);
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;
229 }
230 }
231 /*hcommit_modes();*/
232 hchanuser = &(*hchanuser)->next;
233 }
234 hcommit_modes();
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)
241 if (huser_get_level(tmp->husr) >= H_TRIAL)
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
258 void 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
281 void hchannel_set_topic(hchannel *hchan)
282 {
283 if (hchan->flags & H_HANDLE_TOPIC)
284 helpmod_set_topic(hchan, htopic_construct(hchan->topic));
285 }
286
287 void 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))
294 hchanuser->husr->account = haccount_get_by_name(huser_get_auth(hchanuser->husr));
295 }
296
297 int 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
306 int 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
315 void 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 {
324 hchannel_user *tmp = NULL, **hchanuser = &hchan->channel_users;
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;
334 assert(*hchanuser != NULL);
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
345 int 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
357 int 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
369 int 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
378 void 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
390 void 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
418 int 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
427 void 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 }
443
444 /* goes to schedule */
445 void 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 }
454 }
455
456 const char *hchannel_get_state(hchannel* hchan, int mask)
457 {
458 if (hchan->flags & mask)
459 return "Yes";
460 else
461 return "No";
462 }
463
464 int hchannel_highlight_detection(hchannel *hchan, const char *message)
465 {
466 char buffer[512], *buffer_ptr = buffer, *ptr = buffer;
467 int i, matches = 0;
468
469 strcpy(buffer, message);
470
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;
478 do
479 {
480 nick *tmp;
481 huser *tmp_huser;
482 huser_channel *tmp_huserchan;
483
484 if (i++ > 6)
485 break;
486
487 while (*buffer_ptr && isspace(*buffer_ptr))
488 buffer_ptr++;
489
490 if (*buffer_ptr == '@')
491 buffer_ptr++;
492
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 }
518
519 const 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:
565 return "Require a ticket to join";
566 case 20:
567 return "Send a message on ticket issue";
568 case 21:
569 return "Excessive highlight prevention";
570 default:
571 return "Error, please contact strutsi";
572 }
573 }