]> jfr.im git - irc/rqf/shadowircd.git/blob - src/channel.c
Add channel::exemptchanops, and make +cCDTNG support it.
[irc/rqf/shadowircd.git] / src / channel.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * channel.c: Controls channels.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 *
24 * $Id: channel.c 3580 2007-11-07 23:45:14Z jilles $
25 */
26
27 #include "stdinc.h"
28 #include "channel.h"
29 #include "chmode.h"
30 #include "client.h"
31 #include "common.h"
32 #include "hash.h"
33 #include "hook.h"
34 #include "match.h"
35 #include "ircd.h"
36 #include "numeric.h"
37 #include "s_serv.h" /* captab */
38 #include "s_user.h"
39 #include "send.h"
40 #include "whowas.h"
41 #include "s_conf.h" /* ConfigFileEntry, ConfigChannel */
42 #include "s_newconf.h"
43 #include "logger.h"
44 #include "packet.h"
45
46 struct config_channel_entry ConfigChannel;
47 rb_dlink_list global_channel_list;
48 static rb_bh *channel_heap;
49 static rb_bh *ban_heap;
50 static rb_bh *topic_heap;
51 static rb_bh *member_heap;
52
53 static int channel_capabs[] = { CAP_EX, CAP_IE,
54 CAP_SERVICE,
55 CAP_TS6
56 };
57
58 #define NCHCAPS (sizeof(channel_capabs)/sizeof(int))
59 #define NCHCAP_COMBOS (1 << NCHCAPS)
60
61 static struct ChCapCombo chcap_combos[NCHCAP_COMBOS];
62
63 static void free_topic(struct Channel *chptr);
64
65 static int h_can_join;
66 static int h_can_create_channel;
67 static int h_channel_join;
68
69 /* init_channels()
70 *
71 * input -
72 * output -
73 * side effects - initialises the various blockheaps
74 */
75 void
76 init_channels(void)
77 {
78 channel_heap = rb_bh_create(sizeof(struct Channel), CHANNEL_HEAP_SIZE, "channel_heap");
79 ban_heap = rb_bh_create(sizeof(struct Ban), BAN_HEAP_SIZE, "ban_heap");
80 topic_heap = rb_bh_create(TOPICLEN + 1 + USERHOST_REPLYLEN, TOPIC_HEAP_SIZE, "topic_heap");
81 member_heap = rb_bh_create(sizeof(struct membership), MEMBER_HEAP_SIZE, "member_heap");
82
83 h_can_join = register_hook("can_join");
84 h_channel_join = register_hook("channel_join");
85 h_can_create_channel = register_hook("can_create_channel");
86 }
87
88 /*
89 * allocate_channel - Allocates a channel
90 */
91 struct Channel *
92 allocate_channel(const char *chname)
93 {
94 struct Channel *chptr;
95 chptr = rb_bh_alloc(channel_heap);
96 chptr->chname = rb_strdup(chname);
97 return (chptr);
98 }
99
100 void
101 free_channel(struct Channel *chptr)
102 {
103 rb_free(chptr->chname);
104 rb_bh_free(channel_heap, chptr);
105 }
106
107 struct Ban *
108 allocate_ban(const char *banstr, const char *who)
109 {
110 struct Ban *bptr;
111 bptr = rb_bh_alloc(ban_heap);
112 bptr->banstr = rb_strdup(banstr);
113 bptr->who = rb_strdup(who);
114
115 return (bptr);
116 }
117
118 void
119 free_ban(struct Ban *bptr)
120 {
121 rb_free(bptr->banstr);
122 rb_free(bptr->who);
123 rb_bh_free(ban_heap, bptr);
124 }
125
126
127 /* find_channel_membership()
128 *
129 * input - channel to find them in, client to find
130 * output - membership of client in channel, else NULL
131 * side effects -
132 */
133 struct membership *
134 find_channel_membership(struct Channel *chptr, struct Client *client_p)
135 {
136 struct membership *msptr;
137 rb_dlink_node *ptr;
138
139 if(!IsClient(client_p))
140 return NULL;
141
142 /* Pick the most efficient list to use to be nice to things like
143 * CHANSERV which could be in a large number of channels
144 */
145 if(rb_dlink_list_length(&chptr->members) < rb_dlink_list_length(&client_p->user->channel))
146 {
147 RB_DLINK_FOREACH(ptr, chptr->members.head)
148 {
149 msptr = ptr->data;
150
151 if(msptr->client_p == client_p)
152 return msptr;
153 }
154 }
155 else
156 {
157 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
158 {
159 msptr = ptr->data;
160
161 if(msptr->chptr == chptr)
162 return msptr;
163 }
164 }
165
166 return NULL;
167 }
168
169 /* find_channel_status()
170 *
171 * input - membership to get status for, whether we can combine flags
172 * output - flags of user on channel
173 * side effects -
174 */
175 const char *
176 find_channel_status(struct membership *msptr, int combine)
177 {
178 static char buffer[5];
179 char *p;
180
181 p = buffer;
182
183 if(is_owner(msptr))
184 {
185 if(!combine)
186 return "!";
187 *p++ = '!';
188 }
189
190 if(is_chanop(msptr))
191 {
192 if(!combine)
193 return "@";
194 *p++ = '@';
195 }
196
197 if(is_halfop(msptr))
198 {
199 if(!combine)
200 return "%";
201 *p++ = '%';
202 }
203
204 if(is_voiced(msptr))
205 *p++ = '+';
206
207 *p = '\0';
208 return buffer;
209 }
210
211 /* is_halfop()
212 *
213 * input - membership to check for halfops
214 * output - 1 if the user is halfopped, 0 if the user is not or halfop
215 * is disabled.
216 * side effects -
217 *
218 */
219 int
220 is_halfop(struct membership *msptr)
221 {
222 if(!ConfigChannel.use_halfop)
223 return 0;
224 if(is_chmode_h(msptr))
225 return 1;
226 else
227 return 0;
228 }
229
230 /* is_owner()
231 *
232 * input - membership to check for owner
233 * output - 1 if the user is an owner, 0 if the user is not or owner
234 * is disabled.
235 * side effects -
236 *
237 */
238 int
239 is_owner(struct membership *msptr)
240 {
241 if(!ConfigChannel.use_owner)
242 return 0;
243 if(is_chmode_a(msptr))
244 return 1;
245 else
246 return 0;
247 }
248
249 /* is_any_op()
250 *
251 * input - membership to check for ops
252 * output - 1 if the user is op, halfop, or owner, 0 elsewise
253 * side effects -
254 */
255 int
256 is_any_op(struct membership *msptr)
257 {
258 if(is_chanop(msptr) || is_halfop(msptr) || is_owner(msptr))
259 return 1;
260 else
261 return 0;
262 }
263
264 /* is_chanop_voiced()
265 *
266 * input - memebership to check for status
267 * output - 1 if the user is op, halfop, owner, or voice, 0 elsewise
268 * side effects -
269 */
270 int
271 is_chanop_voiced(struct membership *msptr)
272 {
273 if(is_chanop(msptr) || is_voiced(msptr) || is_halfop(msptr) || is_owner(msptr))
274 return 1;
275 else
276 return 0;
277 }
278
279 /* can_kick_deop()
280 *
281 * input - two memeberships
282 * output - 1 if the first memebership can kick/deop the second, 0 elsewise
283 * side effects -
284 */
285 int
286 can_kick_deop(struct membership *source, struct membership *target)
287 {
288 if(is_chanop(source) && !is_owner(target))
289 return 1;
290 else if(is_halfop(source) && !is_any_op(target))
291 return 1;
292 else if(is_owner(source))
293 return 1;
294
295 return 0;
296 }
297
298 /* add_user_to_channel()
299 *
300 * input - channel to add client to, client to add, channel flags
301 * output -
302 * side effects - user is added to channel
303 */
304 void
305 add_user_to_channel(struct Channel *chptr, struct Client *client_p, int flags)
306 {
307 struct membership *msptr;
308
309 s_assert(client_p->user != NULL);
310 if(client_p->user == NULL)
311 return;
312
313 msptr = rb_bh_alloc(member_heap);
314
315 msptr->chptr = chptr;
316 msptr->client_p = client_p;
317 msptr->flags = flags;
318
319 rb_dlinkAdd(msptr, &msptr->usernode, &client_p->user->channel);
320 rb_dlinkAdd(msptr, &msptr->channode, &chptr->members);
321
322 if(MyClient(client_p))
323 rb_dlinkAdd(msptr, &msptr->locchannode, &chptr->locmembers);
324 }
325
326 /* remove_user_from_channel()
327 *
328 * input - membership pointer to remove from channel
329 * output -
330 * side effects - membership (thus user) is removed from channel
331 */
332 void
333 remove_user_from_channel(struct membership *msptr)
334 {
335 struct Client *client_p;
336 struct Channel *chptr;
337 s_assert(msptr != NULL);
338 if(msptr == NULL)
339 return;
340
341 client_p = msptr->client_p;
342 chptr = msptr->chptr;
343
344 rb_dlinkDelete(&msptr->usernode, &client_p->user->channel);
345 rb_dlinkDelete(&msptr->channode, &chptr->members);
346
347 if(client_p->servptr == &me)
348 rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
349
350 if(!(chptr->mode.mode & MODE_PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
351 destroy_channel(chptr);
352
353 rb_bh_free(member_heap, msptr);
354
355 return;
356 }
357
358 /* remove_user_from_channels()
359 *
360 * input - user to remove from all channels
361 * output -
362 * side effects - user is removed from all channels
363 */
364 void
365 remove_user_from_channels(struct Client *client_p)
366 {
367 struct Channel *chptr;
368 struct membership *msptr;
369 rb_dlink_node *ptr;
370 rb_dlink_node *next_ptr;
371
372 if(client_p == NULL)
373 return;
374
375 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->user->channel.head)
376 {
377 msptr = ptr->data;
378 chptr = msptr->chptr;
379
380 rb_dlinkDelete(&msptr->channode, &chptr->members);
381
382 if(client_p->servptr == &me)
383 rb_dlinkDelete(&msptr->locchannode, &chptr->locmembers);
384
385 if(!(chptr->mode.mode & MODE_PERMANENT) && rb_dlink_list_length(&chptr->members) <= 0)
386 destroy_channel(chptr);
387
388 rb_bh_free(member_heap, msptr);
389 }
390
391 client_p->user->channel.head = client_p->user->channel.tail = NULL;
392 client_p->user->channel.length = 0;
393 }
394
395 /* invalidate_bancache_user()
396 *
397 * input - user to invalidate ban cache for
398 * output -
399 * side effects - ban cache is invalidated for all memberships of that user
400 * to be used after a nick change
401 */
402 void
403 invalidate_bancache_user(struct Client *client_p)
404 {
405 struct membership *msptr;
406 rb_dlink_node *ptr;
407
408 if(client_p == NULL)
409 return;
410
411 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
412 {
413 msptr = ptr->data;
414 msptr->bants = 0;
415 msptr->flags &= ~CHFL_BANNED;
416 }
417 }
418
419 /* check_channel_name()
420 *
421 * input - channel name
422 * output - 1 if valid channel name, else 0
423 * side effects -
424 */
425 int
426 check_channel_name(const char *name)
427 {
428 s_assert(name != NULL);
429 if(name == NULL)
430 return 0;
431
432 for (; *name; ++name)
433 {
434 if(!IsChanChar(*name))
435 return 0;
436 }
437
438 return 1;
439 }
440
441 /* free_channel_list()
442 *
443 * input - rb_dlink list to free
444 * output -
445 * side effects - list of b/e/I modes is cleared
446 */
447 void
448 free_channel_list(rb_dlink_list * list)
449 {
450 rb_dlink_node *ptr;
451 rb_dlink_node *next_ptr;
452 struct Ban *actualBan;
453
454 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
455 {
456 actualBan = ptr->data;
457 free_ban(actualBan);
458 }
459
460 list->head = list->tail = NULL;
461 list->length = 0;
462 }
463
464 /* destroy_channel()
465 *
466 * input - channel to destroy
467 * output -
468 * side effects - channel is obliterated
469 */
470 void
471 destroy_channel(struct Channel *chptr)
472 {
473 rb_dlink_node *ptr, *next_ptr;
474
475 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
476 {
477 del_invite(chptr, ptr->data);
478 }
479
480 /* free all bans/exceptions/denies */
481 free_channel_list(&chptr->banlist);
482 free_channel_list(&chptr->exceptlist);
483 free_channel_list(&chptr->invexlist);
484 free_channel_list(&chptr->quietlist);
485
486 /* Free the topic */
487 free_topic(chptr);
488
489 rb_dlinkDelete(&chptr->node, &global_channel_list);
490 del_from_channel_hash(chptr->chname, chptr);
491 free_channel(chptr);
492 }
493
494 /* channel_pub_or_secret()
495 *
496 * input - channel
497 * output - "=" if public, "@" if secret, else "*"
498 * side effects -
499 */
500 static const char *
501 channel_pub_or_secret(struct Channel *chptr)
502 {
503 if(PubChannel(chptr))
504 return ("=");
505 else if(SecretChannel(chptr))
506 return ("@");
507 return ("*");
508 }
509
510 /* channel_member_names()
511 *
512 * input - channel to list, client to list to, show endofnames
513 * output -
514 * side effects - client is given list of users on channel
515 */
516 void
517 channel_member_names(struct Channel *chptr, struct Client *client_p, int show_eon)
518 {
519 struct membership *msptr;
520 struct Client *target_p;
521 rb_dlink_node *ptr;
522 char lbuf[BUFSIZE];
523 char *t;
524 int mlen;
525 int tlen;
526 int cur_len;
527 int is_member;
528 int stack = IsCapable(client_p, CLICAP_MULTI_PREFIX);
529
530 if(ShowChannel(client_p, chptr))
531 {
532 is_member = IsMember(client_p, chptr);
533
534 cur_len = mlen = rb_sprintf(lbuf, form_str(RPL_NAMREPLY),
535 me.name, client_p->name,
536 channel_pub_or_secret(chptr), chptr->chname);
537
538 t = lbuf + cur_len;
539
540 RB_DLINK_FOREACH(ptr, chptr->members.head)
541 {
542 msptr = ptr->data;
543 target_p = msptr->client_p;
544
545 if(IsInvisible(target_p) && !is_member)
546 continue;
547
548 /* space, possible "@+" prefix */
549 if(cur_len + strlen(target_p->name) + 3 >= BUFSIZE - 3)
550 {
551 *(t - 1) = '\0';
552 sendto_one(client_p, "%s", lbuf);
553 cur_len = mlen;
554 t = lbuf + mlen;
555 }
556
557 tlen = rb_sprintf(t, "%s%s ", find_channel_status(msptr, stack),
558 target_p->name);
559
560 cur_len += tlen;
561 t += tlen;
562 }
563
564 /* The old behaviour here was to always output our buffer,
565 * even if there are no clients we can show. This happens
566 * when a client does "NAMES" with no parameters, and all
567 * the clients on a -sp channel are +i. I dont see a good
568 * reason for keeping that behaviour, as it just wastes
569 * bandwidth. --anfl
570 */
571 if(cur_len != mlen)
572 {
573 *(t - 1) = '\0';
574 sendto_one(client_p, "%s", lbuf);
575 }
576 }
577
578 if(show_eon)
579 sendto_one(client_p, form_str(RPL_ENDOFNAMES),
580 me.name, client_p->name, chptr->chname);
581 }
582
583 /* del_invite()
584 *
585 * input - channel to remove invite from, client to remove
586 * output -
587 * side effects - user is removed from invite list, if exists
588 */
589 void
590 del_invite(struct Channel *chptr, struct Client *who)
591 {
592 rb_dlinkFindDestroy(who, &chptr->invites);
593 rb_dlinkFindDestroy(chptr, &who->user->invited);
594 }
595
596 /* is_banned()
597 *
598 * input - channel to check bans for, user to check bans against
599 * optional prebuilt buffers
600 * output - 1 if banned, else 0
601 * side effects -
602 */
603 int
604 is_banned(struct Channel *chptr, struct Client *who, struct membership *msptr,
605 const char *s, const char *s2)
606 {
607 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
608 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
609 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
610 char *s3 = NULL;
611 rb_dlink_node *ptr;
612 struct Ban *actualBan = NULL;
613 struct Ban *actualExcept = NULL;
614
615 if(!MyClient(who))
616 return 0;
617
618 /* if the buffers havent been built, do it here */
619 if(s == NULL)
620 {
621 rb_sprintf(src_host, "%s!%s@%s", who->name, who->username, who->host);
622 rb_sprintf(src_iphost, "%s!%s@%s", who->name, who->username, who->sockhost);
623
624 s = src_host;
625 s2 = src_iphost;
626 }
627 if(who->localClient->mangledhost != NULL)
628 {
629 /* if host mangling mode enabled, also check their real host */
630 if(!strcmp(who->host, who->localClient->mangledhost))
631 {
632 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->orighost);
633 s3 = src_althost;
634 }
635 /* if host mangling mode not enabled and no other spoof,
636 * also check the mangled form of their host */
637 else if (!IsDynSpoof(who))
638 {
639 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->localClient->mangledhost);
640 s3 = src_althost;
641 }
642 }
643
644 RB_DLINK_FOREACH(ptr, chptr->banlist.head)
645 {
646 actualBan = ptr->data;
647 if(match(actualBan->banstr, s) ||
648 match(actualBan->banstr, s2) ||
649 match_cidr(actualBan->banstr, s2) ||
650 match_extban(actualBan->banstr, who, chptr, CHFL_BAN) ||
651 (s3 != NULL && match(actualBan->banstr, s3)))
652 break;
653 else
654 actualBan = NULL;
655 }
656
657 if((actualBan != NULL) && ConfigChannel.use_except)
658 {
659 RB_DLINK_FOREACH(ptr, chptr->exceptlist.head)
660 {
661 actualExcept = ptr->data;
662
663 /* theyre exempted.. */
664 if(match(actualExcept->banstr, s) ||
665 match(actualExcept->banstr, s2) ||
666 match_cidr(actualExcept->banstr, s2) ||
667 match_extban(actualExcept->banstr, who, chptr, CHFL_EXCEPTION) ||
668 (s3 != NULL && match(actualExcept->banstr, s3)))
669 {
670 /* cache the fact theyre not banned */
671 if(msptr != NULL)
672 {
673 msptr->bants = chptr->bants;
674 msptr->flags &= ~CHFL_BANNED;
675 }
676
677 return CHFL_EXCEPTION;
678 }
679 }
680 }
681
682 /* cache the banned/not banned status */
683 if(msptr != NULL)
684 {
685 msptr->bants = chptr->bants;
686
687 if(actualBan != NULL)
688 {
689 msptr->flags |= CHFL_BANNED;
690 return CHFL_BAN;
691 }
692 else
693 {
694 msptr->flags &= ~CHFL_BANNED;
695 return 0;
696 }
697 }
698
699 return ((actualBan ? CHFL_BAN : 0));
700 }
701
702 /* is_quieted()
703 *
704 * input - channel to check bans for, user to check bans against
705 * optional prebuilt buffers
706 * output - 1 if banned, else 0
707 * side effects -
708 */
709 int
710 is_quieted(struct Channel *chptr, struct Client *who, struct membership *msptr,
711 const char *s, const char *s2)
712 {
713 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
714 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
715 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
716 char *s3 = NULL;
717 rb_dlink_node *ptr;
718 struct Ban *actualBan = NULL;
719 struct Ban *actualExcept = NULL;
720
721 if(!MyClient(who))
722 return 0;
723
724 /* if the buffers havent been built, do it here */
725 if(s == NULL)
726 {
727 rb_sprintf(src_host, "%s!%s@%s", who->name, who->username, who->host);
728 rb_sprintf(src_iphost, "%s!%s@%s", who->name, who->username, who->sockhost);
729
730 s = src_host;
731 s2 = src_iphost;
732 }
733 if(who->localClient->mangledhost != NULL)
734 {
735 /* if host mangling mode enabled, also check their real host */
736 if(!strcmp(who->host, who->localClient->mangledhost))
737 {
738 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->orighost);
739 s3 = src_althost;
740 }
741 /* if host mangling mode not enabled and no other spoof,
742 * also check the mangled form of their host */
743 else if (!IsDynSpoof(who))
744 {
745 rb_sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->localClient->mangledhost);
746 s3 = src_althost;
747 }
748 }
749
750 RB_DLINK_FOREACH(ptr, chptr->quietlist.head)
751 {
752 actualBan = ptr->data;
753 if(match(actualBan->banstr, s) ||
754 match(actualBan->banstr, s2) ||
755 match_cidr(actualBan->banstr, s2) ||
756 match_extban(actualBan->banstr, who, chptr, CHFL_QUIET) ||
757 (s3 != NULL && match(actualBan->banstr, s3)))
758 break;
759 else
760 actualBan = NULL;
761 }
762
763 if((actualBan != NULL) && ConfigChannel.use_except)
764 {
765 RB_DLINK_FOREACH(ptr, chptr->exceptlist.head)
766 {
767 actualExcept = ptr->data;
768
769 /* theyre exempted.. */
770 if(match(actualExcept->banstr, s) ||
771 match(actualExcept->banstr, s2) ||
772 match_cidr(actualExcept->banstr, s2) ||
773 match_extban(actualExcept->banstr, who, chptr, CHFL_EXCEPTION) ||
774 (s3 != NULL && match(actualExcept->banstr, s3)))
775 {
776 /* cache the fact theyre not banned */
777 if(msptr != NULL)
778 {
779 msptr->bants = chptr->bants;
780 msptr->flags &= ~CHFL_BANNED;
781 }
782
783 return CHFL_EXCEPTION;
784 }
785 }
786 }
787
788 /* cache the banned/not banned status */
789 if(msptr != NULL)
790 {
791 msptr->bants = chptr->bants;
792
793 if(actualBan != NULL)
794 {
795 msptr->flags |= CHFL_BANNED;
796 return CHFL_BAN;
797 }
798 else
799 {
800 msptr->flags &= ~CHFL_BANNED;
801 return 0;
802 }
803 }
804
805 return ((actualBan ? CHFL_BAN : 0));
806 }
807
808 /* can_join()
809 *
810 * input - client to check, channel to check for, key
811 * output - reason for not being able to join, else 0
812 * side effects -
813 */
814 int
815 can_join(struct Client *source_p, struct Channel *chptr, char *key)
816 {
817 rb_dlink_node *invite = NULL;
818 rb_dlink_node *ptr;
819 struct Ban *invex = NULL;
820 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
821 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
822 char src_althost[NICKLEN + USERLEN + HOSTLEN + 6];
823 int use_althost = 0;
824 int i = 0;
825 hook_data_channel moduledata;
826
827 s_assert(source_p->localClient != NULL);
828
829 if(IsOverride(source_p))
830 return 0;
831
832 rb_sprintf(src_host, "%s!%s@%s", source_p->name, source_p->username, source_p->host);
833 rb_sprintf(src_iphost, "%s!%s@%s", source_p->name, source_p->username, source_p->sockhost);
834 if(source_p->localClient->mangledhost != NULL)
835 {
836 /* if host mangling mode enabled, also check their real host */
837 if(!strcmp(source_p->host, source_p->localClient->mangledhost))
838 {
839 rb_sprintf(src_althost, "%s!%s@%s", source_p->name, source_p->username, source_p->orighost);
840 use_althost = 1;
841 }
842 /* if host mangling mode not enabled and no other spoof,
843 * also check the mangled form of their host */
844 else if (!IsDynSpoof(source_p))
845 {
846 rb_sprintf(src_althost, "%s!%s@%s", source_p->name, source_p->username, source_p->localClient->mangledhost);
847 use_althost = 1;
848 }
849 }
850
851 if((is_banned(chptr, source_p, NULL, src_host, src_iphost)) == CHFL_BAN)
852 return (ERR_BANNEDFROMCHAN);
853
854 if(chptr->mode.mode & MODE_INVITEONLY)
855 {
856 RB_DLINK_FOREACH(invite, source_p->user->invited.head)
857 {
858 if(invite->data == chptr)
859 break;
860 }
861 if(invite == NULL)
862 {
863 if(!ConfigChannel.use_invex)
864 return (ERR_INVITEONLYCHAN);
865 RB_DLINK_FOREACH(ptr, chptr->invexlist.head)
866 {
867 invex = ptr->data;
868 if(match(invex->banstr, src_host)
869 || match(invex->banstr, src_iphost)
870 || match_cidr(invex->banstr, src_iphost)
871 || match_extban(invex->banstr, source_p, chptr, CHFL_INVEX)
872 || (use_althost && match(invex->banstr, src_althost)))
873 break;
874 }
875 if(ptr == NULL)
876 return (ERR_INVITEONLYCHAN);
877 }
878 }
879
880 if(*chptr->mode.key && (EmptyString(key) || irccmp(chptr->mode.key, key)))
881 return (ERR_BADCHANNELKEY);
882
883 if(chptr->mode.limit &&
884 rb_dlink_list_length(&chptr->members) >= (unsigned long) chptr->mode.limit)
885 i = ERR_CHANNELISFULL;
886 if(chptr->mode.mode & MODE_REGONLY && EmptyString(source_p->user->suser))
887 i = ERR_NEEDREGGEDNICK;
888 /* join throttling stuff --nenolod */
889 else if(chptr->mode.join_num > 0 && chptr->mode.join_time > 0)
890 {
891 if ((rb_current_time() - chptr->join_delta <=
892 chptr->mode.join_time) && (chptr->join_count >=
893 chptr->mode.join_num))
894 i = ERR_THROTTLE;
895 }
896
897 /* allow /invite to override +l/+r/+j also -- jilles */
898 if (i != 0 && invite == NULL)
899 {
900 RB_DLINK_FOREACH(invite, source_p->user->invited.head)
901 {
902 if(invite->data == chptr)
903 break;
904 }
905 if (invite == NULL)
906 return i;
907 }
908
909 moduledata.client = source_p;
910 moduledata.chptr = chptr;
911 moduledata.approved = 0;
912
913 call_hook(h_can_join, &moduledata);
914
915 return moduledata.approved;
916 }
917
918 /* can_send()
919 *
920 * input - user to check in channel, membership pointer
921 * output - whether can explicitly send or not, else CAN_SEND_NONOP
922 * side effects -
923 */
924 int
925 can_send(struct Channel *chptr, struct Client *source_p, struct membership *msptr)
926 {
927 if(IsServer(source_p) || IsService(source_p))
928 return CAN_SEND_OPV;
929
930 if(MyClient(source_p) && hash_find_resv(chptr->chname) &&
931 !IsOper(source_p) && !IsExemptResv(source_p))
932 return CAN_SEND_NO;
933
934 if(msptr == NULL)
935 {
936 msptr = find_channel_membership(chptr, source_p);
937
938 if(msptr == NULL)
939 {
940 /* if its +m or +n and theyre not in the channel,
941 * they cant send. we dont check bans here because
942 * theres no possibility of caching them --fl
943 */
944 if(chptr->mode.mode & MODE_NOPRIVMSGS || chptr->mode.mode & MODE_MODERATED)
945 return CAN_SEND_NO;
946 else
947 return CAN_SEND_NONOP;
948 }
949 }
950
951 if(is_chanop_voiced(msptr))
952 return CAN_SEND_OPV;
953
954 if(IsOverride(source_p))
955 return CAN_SEND_NONOP;
956
957 if(chptr->mode.mode & MODE_MODERATED)
958 return CAN_SEND_NO;
959
960 if(MyClient(source_p))
961 {
962 /* cached can_send */
963 if(msptr->bants == chptr->bants)
964 {
965 if(can_send_banned(msptr))
966 return CAN_SEND_NO;
967 }
968 else if(is_banned(chptr, source_p, msptr, NULL, NULL) == CHFL_BAN
969 || is_quieted(chptr, source_p, msptr, NULL, NULL) == CHFL_BAN)
970 return CAN_SEND_NO;
971 }
972
973 return CAN_SEND_NONOP;
974 }
975
976 /* find_bannickchange_channel()
977 * Input: client to check
978 * Output: channel preventing nick change
979 */
980 struct Channel *
981 find_bannickchange_channel(struct Client *client_p)
982 {
983 struct Channel *chptr;
984 struct membership *msptr;
985 rb_dlink_node *ptr;
986 char src_host[NICKLEN + USERLEN + HOSTLEN + 6];
987 char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6];
988
989 if (!MyClient(client_p) || IsOverride(client_p))
990 return NULL;
991
992 rb_sprintf(src_host, "%s!%s@%s", client_p->name, client_p->username, client_p->host);
993 rb_sprintf(src_iphost, "%s!%s@%s", client_p->name, client_p->username, client_p->sockhost);
994
995 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
996 {
997 msptr = ptr->data;
998 chptr = msptr->chptr;
999 if (is_chanop_voiced(msptr))
1000 continue;
1001 /* cached can_send */
1002 if (msptr->bants == chptr->bants)
1003 {
1004 if (can_send_banned(msptr))
1005 return chptr;
1006 }
1007 else if (is_banned(chptr, client_p, msptr, src_host, src_iphost) == CHFL_BAN
1008 || is_quieted(chptr, client_p, msptr, src_host, src_iphost) == CHFL_BAN)
1009 return chptr;
1010 }
1011 return NULL;
1012 }
1013
1014 /* find_nonickchange_channel()
1015 * Input: client to check
1016 * Output: channel preventing nick change
1017 */
1018 struct Channel *
1019 find_nonickchange_channel(struct Client *client_p)
1020 {
1021 struct Channel *chptr;
1022 struct membership *msptr;
1023 rb_dlink_node *ptr;
1024
1025 if (!MyClient(client_p))
1026 return NULL;
1027
1028 RB_DLINK_FOREACH(ptr, client_p->user->channel.head)
1029 {
1030 msptr = ptr->data;
1031 chptr = msptr->chptr;
1032 if (chptr->mode.mode & MODE_NONICK && (!ConfigChannel.exempt_cmode_N || !is_any_op(msptr)))
1033 return chptr;
1034 }
1035 return NULL;
1036 }
1037
1038 /* void check_spambot_warning(struct Client *source_p)
1039 * Input: Client to check, channel name or NULL if this is a part.
1040 * Output: none
1041 * Side-effects: Updates the client's oper_warn_count_down, warns the
1042 * IRC operators if necessary, and updates join_leave_countdown as
1043 * needed.
1044 */
1045 void
1046 check_spambot_warning(struct Client *source_p, const char *name)
1047 {
1048 int t_delta;
1049 int decrement_count;
1050 if((GlobalSetOptions.spam_num &&
1051 (source_p->localClient->join_leave_count >= GlobalSetOptions.spam_num)))
1052 {
1053 if(source_p->localClient->oper_warn_count_down > 0)
1054 source_p->localClient->oper_warn_count_down--;
1055 else
1056 source_p->localClient->oper_warn_count_down = 0;
1057 if(source_p->localClient->oper_warn_count_down == 0 &&
1058 name != NULL)
1059 {
1060 /* Its already known as a possible spambot */
1061 sendto_realops_snomask(SNO_BOTS, L_NETWIDE,
1062 "User %s (%s@%s) trying to join %s is a possible spambot",
1063 source_p->name,
1064 source_p->username, source_p->orighost, name);
1065 source_p->localClient->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
1066 }
1067 }
1068 else
1069 {
1070 if((t_delta =
1071 (rb_current_time() - source_p->localClient->last_leave_time)) >
1072 JOIN_LEAVE_COUNT_EXPIRE_TIME)
1073 {
1074 decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
1075 if(name != NULL)
1076 ;
1077 else if(decrement_count > source_p->localClient->join_leave_count)
1078 source_p->localClient->join_leave_count = 0;
1079 else
1080 source_p->localClient->join_leave_count -= decrement_count;
1081 }
1082 else
1083 {
1084 if((rb_current_time() -
1085 (source_p->localClient->last_join_time)) < GlobalSetOptions.spam_time)
1086 {
1087 /* oh, its a possible spambot */
1088 source_p->localClient->join_leave_count++;
1089 }
1090 }
1091 if(name != NULL)
1092 source_p->localClient->last_join_time = rb_current_time();
1093 else
1094 source_p->localClient->last_leave_time = rb_current_time();
1095 }
1096 }
1097
1098 /* check_splitmode()
1099 *
1100 * input -
1101 * output -
1102 * side effects - compares usercount and servercount against their split
1103 * values and adjusts splitmode accordingly
1104 */
1105 void
1106 check_splitmode(void *unused)
1107 {
1108 if(splitchecking && (ConfigChannel.no_join_on_split || ConfigChannel.no_create_on_split))
1109 {
1110 /* not split, we're being asked to check now because someone
1111 * has left
1112 */
1113 if(!splitmode)
1114 {
1115 if(eob_count < split_servers || Count.total < split_users)
1116 {
1117 splitmode = 1;
1118 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1119 "Network split, activating splitmode");
1120 check_splitmode_ev = rb_event_addish("check_splitmode", check_splitmode, NULL, 2);
1121 }
1122 }
1123 /* in splitmode, check whether its finished */
1124 else if(eob_count >= split_servers && Count.total >= split_users)
1125 {
1126 splitmode = 0;
1127
1128 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1129 "Network rejoined, deactivating splitmode");
1130
1131 rb_event_delete(check_splitmode_ev);
1132 check_splitmode_ev = NULL;
1133 }
1134 }
1135 }
1136
1137
1138 /* allocate_topic()
1139 *
1140 * input - channel to allocate topic for
1141 * output - 1 on success, else 0
1142 * side effects - channel gets a topic allocated
1143 */
1144 static void
1145 allocate_topic(struct Channel *chptr)
1146 {
1147 void *ptr;
1148
1149 if(chptr == NULL)
1150 return;
1151
1152 ptr = rb_bh_alloc(topic_heap);
1153
1154 /* Basically we allocate one large block for the topic and
1155 * the topic info. We then split it up into two and shove it
1156 * in the chptr
1157 */
1158 chptr->topic = ptr;
1159 chptr->topic_info = (char *) ptr + TOPICLEN + 1;
1160 *chptr->topic = '\0';
1161 *chptr->topic_info = '\0';
1162 }
1163
1164 /* free_topic()
1165 *
1166 * input - channel which has topic to free
1167 * output -
1168 * side effects - channels topic is free'd
1169 */
1170 static void
1171 free_topic(struct Channel *chptr)
1172 {
1173 void *ptr;
1174
1175 if(chptr == NULL || chptr->topic == NULL)
1176 return;
1177
1178 /* This is safe for now - If you change allocate_topic you
1179 * MUST change this as well
1180 */
1181 ptr = chptr->topic;
1182 rb_bh_free(topic_heap, ptr);
1183 chptr->topic = NULL;
1184 chptr->topic_info = NULL;
1185 }
1186
1187 /* set_channel_topic()
1188 *
1189 * input - channel, topic to set, topic info and topic ts
1190 * output -
1191 * side effects - channels topic, topic info and TS are set.
1192 */
1193 void
1194 set_channel_topic(struct Channel *chptr, const char *topic, const char *topic_info, time_t topicts)
1195 {
1196 if(strlen(topic) > 0)
1197 {
1198 if(chptr->topic == NULL)
1199 allocate_topic(chptr);
1200 rb_strlcpy(chptr->topic, topic, TOPICLEN + 1);
1201 rb_strlcpy(chptr->topic_info, topic_info, USERHOST_REPLYLEN);
1202 chptr->topic_time = topicts;
1203 }
1204 else
1205 {
1206 if(chptr->topic != NULL)
1207 free_topic(chptr);
1208 chptr->topic_time = 0;
1209 }
1210 }
1211
1212 /* has_common_channel()
1213 *
1214 * input - pointer to client
1215 * - pointer to another client
1216 * output - 1 if the two have a channel in common, 0 elsewise
1217 * side effects - none
1218 */
1219 int
1220 has_common_channel(struct Client *client1, struct Client *client2)
1221 {
1222 rb_dlink_node *ptr;
1223
1224 RB_DLINK_FOREACH(ptr, client1->user->channel.head)
1225 {
1226 if(IsMember(client2, ((struct membership *)ptr->data)->chptr))
1227 return 1;
1228 }
1229 return 0;
1230 }
1231
1232 /* channel_modes()
1233 *
1234 * inputs - pointer to channel
1235 * - pointer to client
1236 * output - string with simple modes
1237 * side effects - result from previous calls overwritten
1238 *
1239 * Stolen from ShadowIRCd 4 --nenolod
1240 */
1241 const char *
1242 channel_modes(struct Channel *chptr, struct Client *client_p)
1243 {
1244 int i;
1245 char buf1[BUFSIZE];
1246 char buf2[BUFSIZE];
1247 static char final[BUFSIZE];
1248 char *mbuf = buf1;
1249 char *pbuf = buf2;
1250
1251 *mbuf++ = '+';
1252 *pbuf = '\0';
1253
1254 for (i = 0; i < 256; i++)
1255 if(chptr->mode.mode & chmode_flags[i])
1256 *mbuf++ = i;
1257
1258 if(chptr->mode.limit)
1259 {
1260 *mbuf++ = 'l';
1261
1262 if(!IsClient(client_p) || IsMember(client_p, chptr))
1263 pbuf += rb_sprintf(pbuf, " %d", chptr->mode.limit);
1264 }
1265
1266 if(*chptr->mode.key)
1267 {
1268 *mbuf++ = 'k';
1269
1270 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
1271 pbuf += rb_sprintf(pbuf, " %s", chptr->mode.key);
1272 }
1273
1274 if(chptr->mode.join_num)
1275 {
1276 *mbuf++ = 'j';
1277
1278 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
1279 pbuf += rb_sprintf(pbuf, " %d:%d", chptr->mode.join_num,
1280 chptr->mode.join_time);
1281 }
1282
1283 if(*chptr->mode.forward && (ConfigChannel.use_forward || !IsClient(client_p)))
1284 {
1285 *mbuf++ = 'f';
1286
1287 if(pbuf > buf2 || !IsClient(client_p) || IsMember(client_p, chptr))
1288 pbuf += rb_sprintf(pbuf, " %s", chptr->mode.forward);
1289 }
1290
1291 *mbuf = '\0';
1292
1293 rb_strlcpy(final, buf1, sizeof final);
1294 rb_strlcat(final, buf2, sizeof final);
1295 return final;
1296 }
1297
1298 /* Now lets do some stuff to keep track of what combinations of
1299 * servers exist...
1300 * Note that the number of combinations doubles each time you add
1301 * something to this list. Each one is only quick if no servers use that
1302 * combination, but if the numbers get too high here MODE will get too
1303 * slow. I suggest if you get more than 7 here, you consider getting rid
1304 * of some and merging or something. If it wasn't for irc+cs we would
1305 * probably not even need to bother about most of these, but unfortunately
1306 * we do. -A1kmm
1307 */
1308
1309 /* void init_chcap_usage_counts(void)
1310 *
1311 * Inputs - none
1312 * Output - none
1313 * Side-effects - Initialises the usage counts to zero. Fills in the
1314 * chcap_yes and chcap_no combination tables.
1315 */
1316 void
1317 init_chcap_usage_counts(void)
1318 {
1319 unsigned long m, c, y, n;
1320
1321 memset(chcap_combos, 0, sizeof(chcap_combos));
1322
1323 /* For every possible combination */
1324 for (m = 0; m < NCHCAP_COMBOS; m++)
1325 {
1326 /* Check each capab */
1327 for (c = y = n = 0; c < NCHCAPS; c++)
1328 {
1329 if((m & (1 << c)) == 0)
1330 n |= channel_capabs[c];
1331 else
1332 y |= channel_capabs[c];
1333 }
1334 chcap_combos[m].cap_yes = y;
1335 chcap_combos[m].cap_no = n;
1336 }
1337 }
1338
1339 /* void set_chcap_usage_counts(struct Client *serv_p)
1340 * Input: serv_p; The client whose capabs to register.
1341 * Output: none
1342 * Side-effects: Increments the usage counts for the correct capab
1343 * combination.
1344 */
1345 void
1346 set_chcap_usage_counts(struct Client *serv_p)
1347 {
1348 int n;
1349
1350 for (n = 0; n < NCHCAP_COMBOS; n++)
1351 {
1352 if(IsCapable(serv_p, chcap_combos[n].cap_yes) &&
1353 NotCapable(serv_p, chcap_combos[n].cap_no))
1354 {
1355 chcap_combos[n].count++;
1356 return;
1357 }
1358 }
1359
1360 /* This should be impossible -A1kmm. */
1361 s_assert(0);
1362 }
1363
1364 /* void set_chcap_usage_counts(struct Client *serv_p)
1365 *
1366 * Inputs - serv_p; The client whose capabs to register.
1367 * Output - none
1368 * Side-effects - Decrements the usage counts for the correct capab
1369 * combination.
1370 */
1371 void
1372 unset_chcap_usage_counts(struct Client *serv_p)
1373 {
1374 int n;
1375
1376 for (n = 0; n < NCHCAP_COMBOS; n++)
1377 {
1378 if(IsCapable(serv_p, chcap_combos[n].cap_yes) &&
1379 NotCapable(serv_p, chcap_combos[n].cap_no))
1380 {
1381 /* Hopefully capabs can't change dynamically or anything... */
1382 s_assert(chcap_combos[n].count > 0);
1383
1384 if(chcap_combos[n].count > 0)
1385 chcap_combos[n].count--;
1386 return;
1387 }
1388 }
1389
1390 /* This should be impossible -A1kmm. */
1391 s_assert(0);
1392 }
1393
1394 /* void send_cap_mode_changes(struct Client *client_p,
1395 * struct Client *source_p,
1396 * struct Channel *chptr, int cap, int nocap)
1397 * Input: The client sending(client_p), the source client(source_p),
1398 * the channel to send mode changes for(chptr)
1399 * Output: None.
1400 * Side-effects: Sends the appropriate mode changes to capable servers.
1401 *
1402 * Reverted back to my original design, except that we now keep a count
1403 * of the number of servers which each combination as an optimisation, so
1404 * the capabs combinations which are not needed are not worked out. -A1kmm
1405 */
1406 void
1407 send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
1408 struct Channel *chptr, struct ChModeChange mode_changes[], int mode_count)
1409 {
1410 static char modebuf[BUFSIZE];
1411 static char parabuf[BUFSIZE];
1412 int i, mbl, pbl, nc, mc, preflen, len;
1413 char *pbuf;
1414 const char *arg;
1415 int dir;
1416 int j;
1417 int cap;
1418 int nocap;
1419 int arglen;
1420
1421 /* Now send to servers... */
1422 for (j = 0; j < NCHCAP_COMBOS; j++)
1423 {
1424 if(chcap_combos[j].count == 0)
1425 continue;
1426
1427 mc = 0;
1428 nc = 0;
1429 pbl = 0;
1430 parabuf[0] = 0;
1431 pbuf = parabuf;
1432 dir = MODE_QUERY;
1433
1434 cap = chcap_combos[j].cap_yes;
1435 nocap = chcap_combos[j].cap_no;
1436
1437 mbl = preflen = rb_sprintf(modebuf, ":%s TMODE %ld %s ",
1438 use_id(source_p), (long) chptr->channelts,
1439 chptr->chname);
1440
1441 /* loop the list of - modes we have */
1442 for (i = 0; i < mode_count; i++)
1443 {
1444 /* if they dont support the cap we need, or they do support a cap they
1445 * cant have, then dont add it to the modebuf.. that way they wont see
1446 * the mode
1447 */
1448 if((mode_changes[i].letter == 0) ||
1449 ((cap & mode_changes[i].caps) != mode_changes[i].caps)
1450 || ((nocap & mode_changes[i].nocaps) != mode_changes[i].nocaps))
1451 continue;
1452
1453 if(!EmptyString(mode_changes[i].id))
1454 arg = mode_changes[i].id;
1455 else
1456 arg = mode_changes[i].arg;
1457
1458 if(arg)
1459 {
1460 arglen = strlen(arg);
1461
1462 /* dont even think about it! --fl */
1463 if(arglen > MODEBUFLEN - 5)
1464 continue;
1465 }
1466
1467 /* if we're creeping past the buf size, we need to send it and make
1468 * another line for the other modes
1469 * XXX - this could give away server topology with uids being
1470 * different lengths, but not much we can do, except possibly break
1471 * them as if they were the longest of the nick or uid at all times,
1472 * which even then won't work as we don't always know the uid -A1kmm.
1473 */
1474 if(arg && ((mc == MAXMODEPARAMSSERV) ||
1475 ((mbl + pbl + arglen + 4) > (BUFSIZE - 3))))
1476 {
1477 if(nc != 0)
1478 sendto_server(client_p, chptr, cap, nocap,
1479 "%s %s", modebuf, parabuf);
1480 nc = 0;
1481 mc = 0;
1482
1483 mbl = preflen;
1484 pbl = 0;
1485 pbuf = parabuf;
1486 parabuf[0] = 0;
1487 dir = MODE_QUERY;
1488 }
1489
1490 if(dir != mode_changes[i].dir)
1491 {
1492 modebuf[mbl++] = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
1493 dir = mode_changes[i].dir;
1494 }
1495
1496 modebuf[mbl++] = mode_changes[i].letter;
1497 modebuf[mbl] = 0;
1498 nc++;
1499
1500 if(arg != NULL)
1501 {
1502 len = rb_sprintf(pbuf, "%s ", arg);
1503 pbuf += len;
1504 pbl += len;
1505 mc++;
1506 }
1507 }
1508
1509 if(pbl && parabuf[pbl - 1] == ' ')
1510 parabuf[pbl - 1] = 0;
1511
1512 if(nc != 0)
1513 sendto_server(client_p, chptr, cap, nocap, "%s %s", modebuf, parabuf);
1514 }
1515 }
1516
1517 /* Check what we will forward to, without sending any notices to the user
1518 * -- jilles
1519 */
1520 struct Channel *
1521 check_forward(struct Client *source_p, struct Channel *chptr,
1522 char *key)
1523 {
1524 int depth = 0, i;
1525
1526 /* User is +Q */
1527 if (IsNoForward(source_p))
1528 return NULL;
1529
1530 while (depth < 16)
1531 {
1532 chptr = find_channel(chptr->mode.forward);
1533 /* Can only forward to existing channels */
1534 if (chptr == NULL)
1535 return NULL;
1536 /* Already on there, show original error message */
1537 if (IsMember(source_p, chptr))
1538 return NULL;
1539 /* Juped. Sending a warning notice would be unfair */
1540 if (hash_find_resv(chptr->chname))
1541 return NULL;
1542 /* Don't forward to +Q channel */
1543 if (chptr->mode.mode & MODE_DISFORWARD)
1544 return NULL;
1545 i = can_join(source_p, chptr, key);
1546 if (i == 0)
1547 return chptr;
1548 if (i != ERR_INVITEONLYCHAN && i != ERR_NEEDREGGEDNICK && i != ERR_THROTTLE && i != ERR_CHANNELISFULL)
1549 return NULL;
1550 depth++;
1551 }
1552
1553 return NULL;
1554 }
1555
1556 /*
1557 * do_join_0
1558 *
1559 * inputs - pointer to client doing join 0
1560 * output - NONE
1561 * side effects - Use has decided to join 0. This is legacy
1562 * from the days when channels were numbers not names. *sigh*
1563 */
1564 void
1565 do_join_0(struct Client *client_p, struct Client *source_p)
1566 {
1567 struct membership *msptr;
1568 struct Channel *chptr = NULL;
1569 rb_dlink_node *ptr;
1570
1571 /* Finish the flood grace period... */
1572 if(MyClient(source_p) && !IsFloodDone(source_p))
1573 flood_endgrace(source_p);
1574
1575 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s JOIN 0", use_id(source_p));
1576
1577 while((ptr = source_p->user->channel.head))
1578 {
1579 if(source_p->user->channel.head && MyConnect(source_p) &&
1580 !IsOper(source_p) && !IsExemptSpambot(source_p))
1581 check_spambot_warning(source_p, NULL);
1582
1583 msptr = ptr->data;
1584 chptr = msptr->chptr;
1585 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
1586 source_p->name,
1587 source_p->username, source_p->host, chptr->chname);
1588 remove_user_from_channel(msptr);
1589 }
1590 }
1591
1592 int
1593 check_channel_name_loc(struct Client *source_p, const char *name)
1594 {
1595 const char *p;
1596
1597 s_assert(name != NULL);
1598 if(EmptyString(name))
1599 return 0;
1600
1601 if(ConfigFileEntry.disable_fake_channels && !IsOper(source_p))
1602 {
1603 for(p = name; *p; ++p)
1604 {
1605 if(!IsChanChar(*p) || IsFakeChanChar(*p))
1606 return 0;
1607 }
1608 }
1609 else
1610 {
1611 for(p = name; *p; ++p)
1612 {
1613 if(!IsChanChar(*p))
1614 return 0;
1615 }
1616 }
1617
1618 if(ConfigChannel.only_ascii_channels)
1619 {
1620 for(p = name; *p; ++p)
1621 if(*p < 33 || *p > 126)
1622 return 0;
1623 }
1624
1625
1626 return 1;
1627 }
1628
1629 void user_join(struct Client * client_p, struct Client * source_p, const char * channels, const char * keys)
1630 {
1631 static char jbuf[BUFSIZE];
1632 struct Channel *chptr = NULL;
1633 struct ConfItem *aconf;
1634 char *name;
1635 char *key = NULL;
1636 const char *modes;
1637 int i, flags = 0;
1638 char *p = NULL, *p2 = NULL;
1639 char *chanlist;
1640 char *mykey;
1641
1642 jbuf[0] = '\0';
1643
1644 if(channels == NULL)
1645 return;
1646
1647 /* rebuild the list of channels theyre supposed to be joining.
1648 * this code has a side effect of losing keys, but..
1649 */
1650 chanlist = LOCAL_COPY(channels);
1651 for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
1652 {
1653 /* check the length and name of channel is ok */
1654 if(!check_channel_name_loc(source_p, name) || (strlen(name) > LOC_CHANNELLEN))
1655 {
1656 sendto_one_numeric(source_p, ERR_BADCHANNAME,
1657 form_str(ERR_BADCHANNAME), (unsigned char *) name);
1658 continue;
1659 }
1660
1661 /* join 0 parts all channels */
1662 if(*name == '0' && (name[1] == ',' || name[1] == '\0') && name == chanlist)
1663 {
1664 (void) strcpy(jbuf, "0");
1665 continue;
1666 }
1667
1668 /* check it begins with # or &, and local chans are disabled */
1669 else if(!IsChannelName(name) ||
1670 ( !ConfigChannel.use_local_channels && name[0] == '&'))
1671 {
1672 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
1673 form_str(ERR_NOSUCHCHANNEL), name);
1674 continue;
1675 }
1676
1677 /* see if its resv'd */
1678 if(!IsExemptResv(source_p) && (aconf = hash_find_resv(name)))
1679 {
1680 sendto_one_numeric(source_p, ERR_BADCHANNAME,
1681 form_str(ERR_BADCHANNAME), name);
1682
1683 /* dont warn for opers */
1684 if(!IsExemptJupe(source_p) && !IsOper(source_p))
1685 sendto_realops_snomask(SNO_SPY, L_NETWIDE,
1686 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
1687 source_p->name, source_p->username,
1688 source_p->orighost, name, aconf->passwd);
1689 /* dont update tracking for jupe exempt users, these
1690 * are likely to be spamtrap leaves
1691 */
1692 else if(IsExemptJupe(source_p))
1693 aconf->port--;
1694
1695 continue;
1696 }
1697
1698 if(splitmode && !IsOper(source_p) && (*name != '&') &&
1699 ConfigChannel.no_join_on_split)
1700 {
1701 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
1702 me.name, source_p->name, name);
1703 continue;
1704 }
1705
1706 if(*jbuf)
1707 (void) strcat(jbuf, ",");
1708 (void) rb_strlcat(jbuf, name, sizeof(jbuf));
1709 }
1710
1711 if(keys != NULL)
1712 {
1713 mykey = LOCAL_COPY(keys);
1714 key = rb_strtok_r(mykey, ",", &p2);
1715 }
1716
1717 for(name = rb_strtok_r(jbuf, ",", &p); name;
1718 key = (key) ? rb_strtok_r(NULL, ",", &p2) : NULL, name = rb_strtok_r(NULL, ",", &p))
1719 {
1720 hook_data_channel_activity hook_info;
1721
1722 /* JOIN 0 simply parts all channels the user is in */
1723 if(*name == '0' && !atoi(name))
1724 {
1725 if(source_p->user->channel.head == NULL)
1726 continue;
1727
1728 do_join_0(&me, source_p);
1729 continue;
1730 }
1731
1732 /* look for the channel */
1733 if((chptr = find_channel(name)) != NULL)
1734 {
1735 if(IsMember(source_p, chptr))
1736 continue;
1737
1738 flags = 0;
1739 }
1740 else
1741 {
1742 hook_data_client_approval moduledata;
1743
1744 moduledata.client = source_p;
1745 moduledata.approved = 0;
1746
1747 call_hook(h_can_create_channel, &moduledata);
1748
1749 if(moduledata.approved != 0)
1750 {
1751 sendto_one(source_p, form_str(moduledata.approved),
1752 me.name, source_p->name, name);
1753 continue;
1754 }
1755
1756 if(splitmode && !IsOper(source_p) && (*name != '&') &&
1757 ConfigChannel.no_create_on_split)
1758 {
1759 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
1760 me.name, source_p->name, name);
1761 continue;
1762 }
1763
1764 flags = CHFL_CHANOP;
1765 }
1766
1767 if((rb_dlink_list_length(&source_p->user->channel) >=
1768 (unsigned long) ConfigChannel.max_chans_per_user) &&
1769 (!IsOper(source_p) ||
1770 (rb_dlink_list_length(&source_p->user->channel) >=
1771 (unsigned long) ConfigChannel.max_chans_per_user * 3)))
1772 {
1773 sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
1774 me.name, source_p->name, name);
1775 return;
1776 }
1777
1778 if(chptr == NULL) /* If I already have a chptr, no point doing this */
1779 {
1780 chptr = get_or_create_channel(source_p, name, NULL);
1781
1782 if(chptr == NULL)
1783 {
1784 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
1785 me.name, source_p->name, name);
1786 continue;
1787 }
1788 }
1789
1790 /* can_join checks for +i key, bans etc */
1791 if((i = can_join(source_p, chptr, key)))
1792 {
1793 if ((i != ERR_NEEDREGGEDNICK && i != ERR_THROTTLE && i != ERR_INVITEONLYCHAN && i != ERR_CHANNELISFULL) ||
1794 (!ConfigChannel.use_forward || (chptr = check_forward(source_p, chptr, key)) == NULL))
1795 {
1796 /* might be wrong, but is there any other better location for such?
1797 * see extensions/chm_operonly.c for other comments on this
1798 * -- dwr
1799 */
1800 if(i != ERR_CUSTOM)
1801 sendto_one(source_p, form_str(i), me.name, source_p->name, name);
1802
1803 continue;
1804 }
1805
1806 sendto_one_numeric(source_p, ERR_LINKCHANNEL, form_str(ERR_LINKCHANNEL), name, chptr->chname);
1807 }
1808
1809 if(flags == 0 &&
1810 !IsOper(source_p) && !IsExemptSpambot(source_p))
1811 check_spambot_warning(source_p, name);
1812
1813 /* add the user to the channel */
1814 add_user_to_channel(chptr, source_p, flags);
1815 if (chptr->mode.join_num &&
1816 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
1817 {
1818 chptr->join_count = 0;
1819 chptr->join_delta = rb_current_time();
1820 }
1821 chptr->join_count++;
1822
1823 /* we send the user their join here, because we could have to
1824 * send a mode out next.
1825 */
1826 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
1827 source_p->name,
1828 source_p->username, source_p->host, chptr->chname);
1829
1830 /* its a new channel, set +nt and burst. */
1831 if(flags & CHFL_CHANOP)
1832 {
1833 chptr->channelts = rb_current_time();
1834
1835 /* autochanmodes stuff */
1836 if(ConfigChannel.autochanmodes)
1837 {
1838 char * ch;
1839 for(ch = ConfigChannel.autochanmodes; *ch; *ch++)
1840 {
1841 chptr->mode.mode |= chmode_table[*ch].mode_type;
1842 }
1843 }
1844 else
1845 {
1846 chptr->mode.mode |= MODE_TOPICLIMIT;
1847 chptr->mode.mode |= MODE_NOPRIVMSGS;
1848 }
1849
1850 modes = channel_modes(chptr, &me);
1851
1852 sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s %s",
1853 me.name, chptr->chname, modes);
1854
1855 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
1856 ":%s SJOIN %ld %s %s :@%s",
1857 me.id, (long) chptr->channelts,
1858 chptr->chname, modes, source_p->id);
1859 }
1860 else
1861 {
1862 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
1863 ":%s JOIN %ld %s +",
1864 use_id(source_p), (long) chptr->channelts,
1865 chptr->chname);
1866 }
1867
1868 del_invite(chptr, source_p);
1869
1870 if(chptr->topic != NULL)
1871 {
1872 sendto_one(source_p, form_str(RPL_TOPIC), me.name,
1873 source_p->name, chptr->chname, chptr->topic);
1874
1875 sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
1876 me.name, source_p->name, chptr->chname,
1877 chptr->topic_info, chptr->topic_time);
1878 }
1879
1880 channel_member_names(chptr, source_p, 1);
1881
1882 hook_info.client = source_p;
1883 hook_info.chptr = chptr;
1884 hook_info.key = key;
1885 call_hook(h_channel_join, &hook_info);
1886 }
1887
1888 return;
1889 }