]> jfr.im git - irc/rqf/shadowircd.git/blob - modules/core/m_join.c
Start moving parts of join to channels.c so they can be used in more places.
[irc/rqf/shadowircd.git] / modules / core / m_join.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_join.c: Joins a channel.
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: m_join.c 3494 2007-05-27 13:07:27Z jilles $
25 */
26
27 #include "stdinc.h"
28 #include "channel.h"
29 #include "client.h"
30 #include "common.h"
31 #include "hash.h"
32 #include "match.h"
33 #include "ircd.h"
34 #include "numeric.h"
35 #include "send.h"
36 #include "s_serv.h"
37 #include "s_conf.h"
38 #include "s_newconf.h"
39 #include "msg.h"
40 #include "parse.h"
41 #include "modules.h"
42 #include "packet.h"
43 #include "chmode.h"
44
45 static int m_join(struct Client *, struct Client *, int, const char **);
46 static int ms_join(struct Client *, struct Client *, int, const char **);
47 static int ms_sjoin(struct Client *, struct Client *, int, const char **);
48
49 static int h_can_create_channel;
50 static int h_channel_join;
51
52 struct Message join_msgtab = {
53 "JOIN", 0, 0, 0, MFLG_SLOW,
54 {mg_unreg, {m_join, 2}, {ms_join, 2}, mg_ignore, mg_ignore, {m_join, 2}}
55 };
56
57 struct Message sjoin_msgtab = {
58 "SJOIN", 0, 0, 0, MFLG_SLOW,
59 {mg_unreg, mg_ignore, mg_ignore, {ms_sjoin, 4}, mg_ignore, mg_ignore}
60 };
61
62 mapi_clist_av1 join_clist[] = { &join_msgtab, &sjoin_msgtab, NULL };
63
64 mapi_hlist_av1 join_hlist[] = {
65 { "can_create_channel", &h_can_create_channel },
66 { "channel_join", &h_channel_join },
67 { NULL, NULL },
68 };
69
70 DECLARE_MODULE_AV1(join, NULL, NULL, join_clist, join_hlist, NULL, "$Revision: 3494 $");
71
72 static void do_join_0(struct Client *client_p, struct Client *source_p);
73 static int check_channel_name_loc(struct Client *source_p, const char *name);
74
75 static void set_final_mode(struct Mode *mode, struct Mode *oldmode);
76 static void remove_our_modes(struct Channel *chptr, struct Client *source_p);
77
78 static void remove_ban_list(struct Channel *chptr, struct Client *source_p,
79 rb_dlink_list * list, char c, int mems);
80
81 static char modebuf[MODEBUFLEN];
82 static char parabuf[MODEBUFLEN];
83 static const char *para[MAXMODEPARAMS];
84 static char *mbuf;
85 static int pargs;
86
87 /*
88 * m_join
89 * parv[1] = channel
90 * parv[2] = channel password (key)
91 */
92 static int
93 m_join(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
94 {
95 static char jbuf[BUFSIZE];
96 struct Channel *chptr = NULL;
97 struct ConfItem *aconf;
98 char *name;
99 char *key = NULL;
100 const char *modes;
101 int i, flags = 0;
102 char *p = NULL, *p2 = NULL;
103 char *chanlist;
104 char *mykey;
105
106 jbuf[0] = '\0';
107
108 /* rebuild the list of channels theyre supposed to be joining.
109 * this code has a side effect of losing keys, but..
110 */
111 chanlist = LOCAL_COPY(parv[1]);
112 for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p))
113 {
114 /* check the length and name of channel is ok */
115 if(!check_channel_name_loc(source_p, name) || (strlen(name) > LOC_CHANNELLEN))
116 {
117 sendto_one_numeric(source_p, ERR_BADCHANNAME,
118 form_str(ERR_BADCHANNAME), (unsigned char *) name);
119 continue;
120 }
121
122 /* join 0 parts all channels */
123 if(*name == '0' && (name[1] == ',' || name[1] == '\0') && name == chanlist)
124 {
125 (void) strcpy(jbuf, "0");
126 continue;
127 }
128
129 /* check it begins with # or &, and local chans are disabled */
130 else if(!IsChannelName(name))
131 {
132 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
133 form_str(ERR_NOSUCHCHANNEL), name);
134 continue;
135 }
136
137 /* see if its resv'd */
138 if(!IsExemptResv(source_p) && (aconf = hash_find_resv(name)))
139 {
140 sendto_one_numeric(source_p, ERR_BADCHANNAME,
141 form_str(ERR_BADCHANNAME), name);
142
143 /* dont warn for opers */
144 if(!IsExemptJupe(source_p) && !IsOper(source_p))
145 sendto_realops_snomask(SNO_SPY, L_NETWIDE,
146 "User %s (%s@%s) is attempting to join locally juped channel %s (%s)",
147 source_p->name, source_p->username,
148 source_p->orighost, name, aconf->passwd);
149 /* dont update tracking for jupe exempt users, these
150 * are likely to be spamtrap leaves
151 */
152 else if(IsExemptJupe(source_p))
153 aconf->port--;
154
155 continue;
156 }
157
158 if(splitmode && !IsOper(source_p) && (*name != '&') &&
159 ConfigChannel.no_join_on_split)
160 {
161 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
162 me.name, source_p->name, name);
163 continue;
164 }
165
166 if(*jbuf)
167 (void) strcat(jbuf, ",");
168 (void) rb_strlcat(jbuf, name, sizeof(jbuf));
169 }
170
171 if(parc > 2)
172 {
173 mykey = LOCAL_COPY(parv[2]);
174 key = rb_strtok_r(mykey, ",", &p2);
175 }
176
177 for(name = rb_strtok_r(jbuf, ",", &p); name;
178 key = (key) ? rb_strtok_r(NULL, ",", &p2) : NULL, name = rb_strtok_r(NULL, ",", &p))
179 {
180 hook_data_channel_activity hook_info;
181
182 /* JOIN 0 simply parts all channels the user is in */
183 if(*name == '0' && !atoi(name))
184 {
185 if(source_p->user->channel.head == NULL)
186 continue;
187
188 do_join_0(&me, source_p);
189 continue;
190 }
191
192 /* look for the channel */
193 if((chptr = find_channel(name)) != NULL)
194 {
195 if(IsMember(source_p, chptr))
196 continue;
197
198 flags = 0;
199 }
200 else
201 {
202 hook_data_client_approval moduledata;
203
204 moduledata.client = source_p;
205 moduledata.approved = 0;
206
207 call_hook(h_can_create_channel, &moduledata);
208
209 if(moduledata.approved != 0)
210 {
211 sendto_one(source_p, form_str(moduledata.approved),
212 me.name, source_p->name, name);
213 continue;
214 }
215
216 if(splitmode && !IsOper(source_p) && (*name != '&') &&
217 ConfigChannel.no_create_on_split)
218 {
219 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
220 me.name, source_p->name, name);
221 continue;
222 }
223
224 flags = CHFL_CHANOP;
225 }
226
227 if((rb_dlink_list_length(&source_p->user->channel) >=
228 (unsigned long) ConfigChannel.max_chans_per_user) &&
229 (!IsOper(source_p) ||
230 (rb_dlink_list_length(&source_p->user->channel) >=
231 (unsigned long) ConfigChannel.max_chans_per_user * 3)))
232 {
233 sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS),
234 me.name, source_p->name, name);
235 return 0;
236 }
237
238 if(chptr == NULL) /* If I already have a chptr, no point doing this */
239 {
240 chptr = get_or_create_channel(source_p, name, NULL);
241
242 if(chptr == NULL)
243 {
244 sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE),
245 me.name, source_p->name, name);
246 continue;
247 }
248 }
249
250 /* can_join checks for +i key, bans etc */
251 if((i = can_join(source_p, chptr, key)))
252 {
253 if ((i != ERR_NEEDREGGEDNICK && i != ERR_THROTTLE && i != ERR_INVITEONLYCHAN && i != ERR_CHANNELISFULL) ||
254 (!ConfigChannel.use_forward || (chptr = check_forward(source_p, chptr, key)) == NULL))
255 {
256 /* might be wrong, but is there any other better location for such?
257 * see extensions/chm_operonly.c for other comments on this
258 * -- dwr
259 */
260 if(i != ERR_CUSTOM)
261 sendto_one(source_p, form_str(i), me.name, source_p->name, name);
262
263 continue;
264 }
265
266 sendto_one_numeric(source_p, ERR_LINKCHANNEL, form_str(ERR_LINKCHANNEL), name, chptr->chname);
267 }
268
269 if(flags == 0 &&
270 !IsOper(source_p) && !IsExemptSpambot(source_p))
271 check_spambot_warning(source_p, name);
272
273 /* add the user to the channel */
274 add_user_to_channel(chptr, source_p, flags);
275 if (chptr->mode.join_num &&
276 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
277 {
278 chptr->join_count = 0;
279 chptr->join_delta = rb_current_time();
280 }
281 chptr->join_count++;
282
283 /* we send the user their join here, because we could have to
284 * send a mode out next.
285 */
286 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
287 source_p->name,
288 source_p->username, source_p->host, chptr->chname);
289
290 /* its a new channel, set +nt and burst. */
291 if(flags & CHFL_CHANOP)
292 {
293 chptr->channelts = rb_current_time();
294 chptr->mode.mode |= MODE_TOPICLIMIT;
295 chptr->mode.mode |= MODE_NOPRIVMSGS;
296 modes = channel_modes(chptr, &me);
297
298 sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s %s",
299 me.name, chptr->chname, modes);
300
301 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
302 ":%s SJOIN %ld %s %s :@%s",
303 me.id, (long) chptr->channelts,
304 chptr->chname, modes, source_p->id);
305 }
306 else
307 {
308 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
309 ":%s JOIN %ld %s +",
310 use_id(source_p), (long) chptr->channelts,
311 chptr->chname);
312 }
313
314 del_invite(chptr, source_p);
315
316 if(chptr->topic != NULL)
317 {
318 sendto_one(source_p, form_str(RPL_TOPIC), me.name,
319 source_p->name, chptr->chname, chptr->topic);
320
321 sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
322 me.name, source_p->name, chptr->chname,
323 chptr->topic_info, chptr->topic_time);
324 }
325
326 channel_member_names(chptr, source_p, 1);
327
328 hook_info.client = source_p;
329 hook_info.chptr = chptr;
330 hook_info.key = key;
331 call_hook(h_channel_join, &hook_info);
332 }
333
334 return 0;
335 }
336
337 /*
338 * ms_join
339 * parv[1] = channel TS
340 * parv[2] = channel
341 * parv[3] = "+", formerly channel modes but now unused
342 * alternatively, a single "0" parameter parts all channels
343 */
344 static int
345 ms_join(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
346 {
347 struct Channel *chptr;
348 static struct Mode mode;
349 time_t oldts;
350 time_t newts;
351 int isnew;
352 int keep_our_modes = YES;
353 int keep_new_modes = YES;
354 rb_dlink_node *ptr, *next_ptr;
355
356 /* special case for join 0 */
357 if((parv[1][0] == '0') && (parv[1][1] == '\0') && parc == 2)
358 {
359 do_join_0(client_p, source_p);
360 return 0;
361 }
362
363 if(parc < 4)
364 return 0;
365
366 if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
367 return 0;
368
369 /* joins for local channels cant happen. */
370 if(parv[2][0] == '&')
371 return 0;
372
373 mbuf = modebuf;
374 mode.key[0] = mode.forward[0] = '\0';
375 mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
376
377 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
378 return 0;
379
380 newts = atol(parv[1]);
381 oldts = chptr->channelts;
382
383 #ifdef IGNORE_BOGUS_TS
384 if(newts < 800000000)
385 {
386 sendto_realops_snomask(SNO_DEBUG, L_ALL,
387 "*** Bogus TS %ld on %s ignored from %s",
388 (long) newts, chptr->chname, client_p->name);
389 newts = (oldts == 0) ? oldts : 800000000;
390 }
391 #else
392 /* making a channel TS0 */
393 if(!isnew && !newts && oldts)
394 {
395 sendto_channel_local(ALL_MEMBERS, chptr,
396 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to 0",
397 me.name, chptr->chname, chptr->chname, (long) oldts);
398 sendto_realops_snomask(SNO_GENERAL, L_ALL,
399 "Server %s changing TS on %s from %ld to 0",
400 source_p->name, chptr->chname, (long) oldts);
401 }
402 #endif
403
404 if(isnew)
405 chptr->channelts = newts;
406 else if(newts == 0 || oldts == 0)
407 chptr->channelts = 0;
408 else if(newts == oldts)
409 ;
410 else if(newts < oldts)
411 {
412 keep_our_modes = NO;
413 chptr->channelts = newts;
414 }
415 else
416 keep_new_modes = NO;
417
418 /* Lost the TS, other side wins, so remove modes on this side */
419 if(!keep_our_modes)
420 {
421 set_final_mode(&mode, &chptr->mode);
422 chptr->mode = mode;
423 remove_our_modes(chptr, source_p);
424 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
425 {
426 del_invite(chptr, ptr->data);
427 }
428 /* If setting -j, clear join throttle state -- jilles */
429 chptr->join_count = chptr->join_delta = 0;
430 sendto_channel_local(ALL_MEMBERS, chptr,
431 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
432 me.name, chptr->chname, chptr->chname,
433 (long) oldts, (long) newts);
434 /* Update capitalization in channel name, this makes the
435 * capitalization timestamped like modes are -- jilles */
436 strcpy(chptr->chname, parv[2]);
437 if(*modebuf != '\0')
438 sendto_channel_local(ALL_MEMBERS, chptr,
439 ":%s MODE %s %s %s",
440 source_p->servptr->name,
441 chptr->chname, modebuf, parabuf);
442 *modebuf = *parabuf = '\0';
443 }
444
445 if(!IsMember(source_p, chptr))
446 {
447 add_user_to_channel(chptr, source_p, CHFL_PEON);
448 if (chptr->mode.join_num &&
449 rb_current_time() - chptr->join_delta >= chptr->mode.join_time)
450 {
451 chptr->join_count = 0;
452 chptr->join_delta = rb_current_time();
453 }
454 chptr->join_count++;
455 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
456 source_p->name, source_p->username,
457 source_p->host, chptr->chname);
458 }
459
460 sendto_server(client_p, chptr, CAP_TS6, NOCAPS,
461 ":%s JOIN %ld %s +",
462 source_p->id, (long) chptr->channelts, chptr->chname);
463 return 0;
464 }
465
466 static int
467 ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
468 {
469 static char buf_uid[BUFSIZE];
470 static const char empty_modes[] = "0";
471 struct Channel *chptr;
472 struct Client *target_p, *fakesource_p;
473 time_t newts;
474 time_t oldts;
475 static struct Mode mode, *oldmode;
476 const char *modes;
477 int args = 0;
478 int keep_our_modes = 1;
479 int keep_new_modes = 1;
480 int fl;
481 int isnew;
482 int mlen_uid;
483 int len_nick;
484 int len_uid;
485 int len;
486 int joins = 0;
487 const char *s;
488 char *ptr_uid;
489 char *p;
490 int i, joinc = 0, timeslice = 0;
491 static char empty[] = "";
492 rb_dlink_node *ptr, *next_ptr;
493
494 if(!IsChannelName(parv[2]) || !check_channel_name(parv[2]))
495 return 0;
496
497 /* SJOIN's for local channels can't happen. */
498 if(*parv[2] == '&')
499 return 0;
500
501 modebuf[0] = parabuf[0] = mode.key[0] = mode.forward[0] = '\0';
502 pargs = mode.mode = mode.limit = mode.join_num = mode.join_time = 0;
503
504 /* Hide connecting server on netburst -- jilles */
505 if (ConfigServerHide.flatten_links && !HasSentEob(source_p))
506 fakesource_p = &me;
507 else
508 fakesource_p = source_p;
509
510 mbuf = modebuf;
511 newts = atol(parv[1]);
512
513 s = parv[3];
514 while (*s)
515 {
516 switch (*(s++))
517 {
518 case 'f':
519 rb_strlcpy(mode.forward, parv[4 + args], sizeof(mode.forward));
520 args++;
521 if(parc < 5 + args)
522 return 0;
523 break;
524 case 'j':
525 sscanf(parv[4 + args], "%d:%d", &joinc, &timeslice);
526 args++;
527 mode.join_num = joinc;
528 mode.join_time = timeslice;
529 if(parc < 5 + args)
530 return 0;
531 break;
532 case 'k':
533 rb_strlcpy(mode.key, parv[4 + args], sizeof(mode.key));
534 args++;
535 if(parc < 5 + args)
536 return 0;
537 break;
538 case 'l':
539 mode.limit = atoi(parv[4 + args]);
540 args++;
541 if(parc < 5 + args)
542 return 0;
543 break;
544 default:
545 if(chmode_flags[(int) *s] != 0)
546 {
547 mode.mode |= chmode_flags[(int) *s];
548 }
549 }
550 }
551
552 if(parv[args + 4])
553 {
554 s = parv[args + 4];
555
556 /* remove any leading spaces */
557 while (*s == ' ')
558 s++;
559 }
560 else
561 s = "";
562
563 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
564 return 0; /* channel name too long? */
565
566
567 oldts = chptr->channelts;
568 oldmode = &chptr->mode;
569
570 #ifdef IGNORE_BOGUS_TS
571 if(newts < 800000000)
572 {
573 sendto_realops_snomask(SNO_DEBUG, L_ALL,
574 "*** Bogus TS %ld on %s ignored from %s",
575 (long) newts, chptr->chname, client_p->name);
576
577 newts = (oldts == 0) ? oldts : 800000000;
578 }
579 #else
580 if(!isnew && !newts && oldts)
581 {
582 sendto_channel_local(ALL_MEMBERS, chptr,
583 ":%s NOTICE %s :*** Notice -- TS for %s "
584 "changed from %ld to 0",
585 me.name, chptr->chname, chptr->chname, (long) oldts);
586 sendto_realops_snomask(SNO_GENERAL, L_ALL,
587 "Server %s changing TS on %s from %ld to 0",
588 source_p->name, chptr->chname, (long) oldts);
589 }
590 #endif
591
592 if(isnew)
593 chptr->channelts = newts;
594
595 else if(newts == 0 || oldts == 0)
596 chptr->channelts = 0;
597 else if(newts == oldts)
598 ;
599 else if(newts < oldts)
600 {
601 /* If configured, kick people trying to join +i/+k
602 * channels by recreating them on split servers.
603 * Don't kick if the source has sent EOB (services
604 * deopping everyone by TS-1 SJOIN).
605 * -- jilles */
606 if (ConfigChannel.kick_on_split_riding &&
607 !HasSentEob(source_p) &&
608 ((mode.mode & MODE_INVITEONLY) ||
609 (mode.key[0] != 0 && irccmp(mode.key, oldmode->key) != 0)))
610 {
611 struct membership *msptr;
612 struct Client *who;
613 int l = rb_dlink_list_length(&chptr->members);
614
615 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
616 {
617 msptr = ptr->data;
618 who = msptr->client_p;
619 sendto_one(who, ":%s KICK %s %s :Net Rider",
620 me.name, chptr->chname, who->name);
621
622 sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
623 ":%s KICK %s %s :Net Rider",
624 me.id, chptr->chname,
625 who->id);
626 remove_user_from_channel(msptr);
627 if (--l == 0)
628 break;
629 }
630 if (l == 0)
631 {
632 /* Channel was emptied, create a new one */
633 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
634 return 0; /* oops! */
635
636 oldmode = &chptr->mode;
637 }
638 }
639 keep_our_modes = NO;
640 chptr->channelts = newts;
641 }
642 else
643 keep_new_modes = NO;
644
645 if(!keep_new_modes)
646 mode = *oldmode;
647 else if(keep_our_modes)
648 {
649 mode.mode |= oldmode->mode;
650 if(oldmode->limit > mode.limit)
651 mode.limit = oldmode->limit;
652 if(strcmp(mode.key, oldmode->key) < 0)
653 strcpy(mode.key, oldmode->key);
654 if(oldmode->join_num > mode.join_num ||
655 (oldmode->join_num == mode.join_num &&
656 oldmode->join_time > mode.join_time))
657 {
658 mode.join_num = oldmode->join_num;
659 mode.join_time = oldmode->join_time;
660 }
661 if(irccmp(mode.forward, oldmode->forward) < 0)
662 strcpy(mode.forward, oldmode->forward);
663 }
664 else
665 {
666 /* If setting -j, clear join throttle state -- jilles */
667 if (!mode.join_num)
668 chptr->join_count = chptr->join_delta = 0;
669 }
670
671 set_final_mode(&mode, oldmode);
672 chptr->mode = mode;
673
674 /* Lost the TS, other side wins, so remove modes on this side */
675 if(!keep_our_modes)
676 {
677 remove_our_modes(chptr, fakesource_p);
678 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
679 {
680 del_invite(chptr, ptr->data);
681 }
682
683 if(rb_dlink_list_length(&chptr->banlist) > 0)
684 remove_ban_list(chptr, fakesource_p, &chptr->banlist, 'b', ALL_MEMBERS);
685 if(rb_dlink_list_length(&chptr->exceptlist) > 0)
686 remove_ban_list(chptr, fakesource_p, &chptr->exceptlist,
687 'e', ONLY_CHANOPS);
688 if(rb_dlink_list_length(&chptr->invexlist) > 0)
689 remove_ban_list(chptr, fakesource_p, &chptr->invexlist,
690 'I', ONLY_CHANOPS);
691 if(rb_dlink_list_length(&chptr->quietlist) > 0)
692 remove_ban_list(chptr, fakesource_p, &chptr->quietlist,
693 'q', ALL_MEMBERS);
694 chptr->bants++;
695
696 sendto_channel_local(ALL_MEMBERS, chptr,
697 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
698 me.name, chptr->chname, chptr->chname,
699 (long) oldts, (long) newts);
700 /* Update capitalization in channel name, this makes the
701 * capitalization timestamped like modes are -- jilles */
702 strcpy(chptr->chname, parv[2]);
703 }
704
705 if(*modebuf != '\0')
706 sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
707 fakesource_p->name, chptr->chname, modebuf, parabuf);
708
709 *modebuf = *parabuf = '\0';
710
711 if(parv[3][0] != '0' && keep_new_modes)
712 modes = channel_modes(chptr, source_p);
713 else
714 modes = empty_modes;
715
716 mlen_uid = rb_sprintf(buf_uid, ":%s SJOIN %ld %s %s :",
717 use_id(source_p), (long) chptr->channelts, parv[2], modes);
718 ptr_uid = buf_uid + mlen_uid;
719
720 mbuf = modebuf;
721 para[0] = para[1] = para[2] = para[3] = empty;
722 pargs = 0;
723 len_nick = len_uid = 0;
724
725 /* if theres a space, theres going to be more than one nick, change the
726 * first space to \0, so s is just the first nick, and point p to the
727 * second nick
728 */
729 if((p = strchr(s, ' ')) != NULL)
730 {
731 *p++ = '\0';
732 }
733
734 *mbuf++ = '+';
735
736 while (s)
737 {
738 fl = 0;
739
740 for (i = 0; i < 2; i++)
741 {
742 if(*s == '@')
743 {
744 fl |= CHFL_CHANOP;
745 s++;
746 }
747 else if(*s == '+')
748 {
749 fl |= CHFL_VOICE;
750 s++;
751 }
752 }
753
754 /* if the client doesnt exist or is fake direction, skip. */
755 if(!(target_p = find_client(s)) ||
756 (target_p->from != client_p) || !IsPerson(target_p))
757 goto nextnick;
758
759 /* we assume for these we can fit at least one nick/uid in.. */
760
761 /* check we can fit another status+nick+space into a buffer */
762 if((mlen_uid + len_uid + IDLEN + 3) > (BUFSIZE - 3))
763 {
764 *(ptr_uid - 1) = '\0';
765 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
766 ptr_uid = buf_uid + mlen_uid;
767 len_uid = 0;
768 }
769
770 if(keep_new_modes)
771 {
772 if(fl & CHFL_CHANOP)
773 {
774 *ptr_uid++ = '@';
775 len_nick++;
776 len_uid++;
777 }
778 if(fl & CHFL_VOICE)
779 {
780 *ptr_uid++ = '+';
781 len_nick++;
782 len_uid++;
783 }
784 }
785
786 /* copy the nick to the two buffers */
787 len = rb_sprintf(ptr_uid, "%s ", use_id(target_p));
788 ptr_uid += len;
789 len_uid += len;
790
791 if(!keep_new_modes)
792 fl = 0;
793
794 if(!IsMember(target_p, chptr))
795 {
796 add_user_to_channel(chptr, target_p, fl);
797 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
798 target_p->name,
799 target_p->username, target_p->host, parv[2]);
800 joins++;
801 }
802
803 if(fl & CHFL_CHANOP)
804 {
805 *mbuf++ = 'o';
806 para[pargs++] = target_p->name;
807
808 /* a +ov user.. bleh */
809 if(fl & CHFL_VOICE)
810 {
811 /* its possible the +o has filled up MAXMODEPARAMS, if so, start
812 * a new buffer
813 */
814 if(pargs >= MAXMODEPARAMS)
815 {
816 *mbuf = '\0';
817 sendto_channel_local(ALL_MEMBERS, chptr,
818 ":%s MODE %s %s %s %s %s %s",
819 fakesource_p->name, chptr->chname,
820 modebuf,
821 para[0], para[1], para[2], para[3]);
822 mbuf = modebuf;
823 *mbuf++ = '+';
824 para[0] = para[1] = para[2] = para[3] = NULL;
825 pargs = 0;
826 }
827
828 *mbuf++ = 'v';
829 para[pargs++] = target_p->name;
830 }
831 }
832 else if(fl & CHFL_VOICE)
833 {
834 *mbuf++ = 'v';
835 para[pargs++] = target_p->name;
836 }
837
838 if(pargs >= MAXMODEPARAMS)
839 {
840 *mbuf = '\0';
841 sendto_channel_local(ALL_MEMBERS, chptr,
842 ":%s MODE %s %s %s %s %s %s",
843 fakesource_p->name,
844 chptr->chname,
845 modebuf, para[0], para[1], para[2], para[3]);
846 mbuf = modebuf;
847 *mbuf++ = '+';
848 para[0] = para[1] = para[2] = para[3] = NULL;
849 pargs = 0;
850 }
851
852 nextnick:
853 /* p points to the next nick */
854 s = p;
855
856 /* if there was a trailing space and p was pointing to it, then we
857 * need to exit.. this has the side effect of breaking double spaces
858 * in an sjoin.. but that shouldnt happen anyway
859 */
860 if(s && (*s == '\0'))
861 s = p = NULL;
862
863 /* if p was NULL due to no spaces, s wont exist due to the above, so
864 * we cant check it for spaces.. if there are no spaces, then when
865 * we next get here, s will be NULL
866 */
867 if(s && ((p = strchr(s, ' ')) != NULL))
868 {
869 *p++ = '\0';
870 }
871 }
872
873 *mbuf = '\0';
874 if(pargs)
875 {
876 sendto_channel_local(ALL_MEMBERS, chptr,
877 ":%s MODE %s %s %s %s %s %s",
878 fakesource_p->name, chptr->chname, modebuf,
879 para[0], CheckEmpty(para[1]),
880 CheckEmpty(para[2]), CheckEmpty(para[3]));
881 }
882
883 if(!joins && !(chptr->mode.mode & MODE_PERMANENT) && isnew)
884 {
885 destroy_channel(chptr);
886
887 return 0;
888 }
889
890 /* Keep the colon if we're sending an SJOIN without nicks -- jilles */
891 if (joins)
892 {
893 *(ptr_uid - 1) = '\0';
894 }
895
896 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
897
898 return 0;
899 }
900
901 /*
902 * do_join_0
903 *
904 * inputs - pointer to client doing join 0
905 * output - NONE
906 * side effects - Use has decided to join 0. This is legacy
907 * from the days when channels were numbers not names. *sigh*
908 */
909 static void
910 do_join_0(struct Client *client_p, struct Client *source_p)
911 {
912 struct membership *msptr;
913 struct Channel *chptr = NULL;
914 rb_dlink_node *ptr;
915
916 /* Finish the flood grace period... */
917 if(MyClient(source_p) && !IsFloodDone(source_p))
918 flood_endgrace(source_p);
919
920 sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s JOIN 0", use_id(source_p));
921
922 while((ptr = source_p->user->channel.head))
923 {
924 if(MyConnect(source_p) &&
925 !IsOper(source_p) && !IsExemptSpambot(source_p))
926 check_spambot_warning(source_p, NULL);
927
928 msptr = ptr->data;
929 chptr = msptr->chptr;
930 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s",
931 source_p->name,
932 source_p->username, source_p->host, chptr->chname);
933 remove_user_from_channel(msptr);
934 }
935 }
936
937 static int
938 check_channel_name_loc(struct Client *source_p, const char *name)
939 {
940 const char *p;
941
942 s_assert(name != NULL);
943 if(EmptyString(name))
944 return 0;
945
946 if(ConfigFileEntry.disable_fake_channels && !IsOper(source_p))
947 {
948 for(p = name; *p; ++p)
949 {
950 if(!IsChanChar(*p) || IsFakeChanChar(*p))
951 return 0;
952 }
953 }
954 else
955 {
956 for(p = name; *p; ++p)
957 {
958 if(!IsChanChar(*p))
959 return 0;
960 }
961 }
962
963 if(ConfigChannel.only_ascii_channels)
964 {
965 for(p = name; *p; ++p)
966 if(*p < 33 || *p > 126)
967 return 0;
968 }
969
970 return 1;
971 }
972
973 static void
974 set_final_mode(struct Mode *mode, struct Mode *oldmode)
975 {
976 int dir = MODE_QUERY;
977 char *pbuf = parabuf;
978 int len;
979 int i;
980
981 /* ok, first get a list of modes we need to add */
982 for (i = 0; i < 256; i++)
983 {
984 if((mode->mode & chmode_flags[i]) && !(oldmode->mode & chmode_flags[i]))
985 {
986 if(dir != MODE_ADD)
987 {
988 *mbuf++ = '+';
989 dir = MODE_ADD;
990 }
991 *mbuf++ = i;
992 }
993 }
994
995 /* now the ones we need to remove. */
996 for (i = 0; i < 256; i++)
997 {
998 if((oldmode->mode & chmode_flags[i]) && !(mode->mode & chmode_flags[i]))
999 {
1000 if(dir != MODE_DEL)
1001 {
1002 *mbuf++ = '-';
1003 dir = MODE_DEL;
1004 }
1005 *mbuf++ = i;
1006 }
1007 }
1008
1009 if(oldmode->limit && !mode->limit)
1010 {
1011 if(dir != MODE_DEL)
1012 {
1013 *mbuf++ = '-';
1014 dir = MODE_DEL;
1015 }
1016 *mbuf++ = 'l';
1017 }
1018 if(oldmode->key[0] && !mode->key[0])
1019 {
1020 if(dir != MODE_DEL)
1021 {
1022 *mbuf++ = '-';
1023 dir = MODE_DEL;
1024 }
1025 *mbuf++ = 'k';
1026 len = rb_sprintf(pbuf, "%s ", oldmode->key);
1027 pbuf += len;
1028 }
1029 if(oldmode->join_num && !mode->join_num)
1030 {
1031 if(dir != MODE_DEL)
1032 {
1033 *mbuf++ = '-';
1034 dir = MODE_DEL;
1035 }
1036 *mbuf++ = 'j';
1037 }
1038 if(oldmode->forward[0] && !mode->forward[0])
1039 {
1040 if(dir != MODE_DEL)
1041 {
1042 *mbuf++ = '-';
1043 dir = MODE_DEL;
1044 }
1045 *mbuf++ = 'f';
1046 }
1047 if(mode->limit && oldmode->limit != mode->limit)
1048 {
1049 if(dir != MODE_ADD)
1050 {
1051 *mbuf++ = '+';
1052 dir = MODE_ADD;
1053 }
1054 *mbuf++ = 'l';
1055 len = rb_sprintf(pbuf, "%d ", mode->limit);
1056 pbuf += len;
1057 }
1058 if(mode->key[0] && strcmp(oldmode->key, mode->key))
1059 {
1060 if(dir != MODE_ADD)
1061 {
1062 *mbuf++ = '+';
1063 dir = MODE_ADD;
1064 }
1065 *mbuf++ = 'k';
1066 len = rb_sprintf(pbuf, "%s ", mode->key);
1067 pbuf += len;
1068 }
1069 if(mode->join_num && (oldmode->join_num != mode->join_num || oldmode->join_time != mode->join_time))
1070 {
1071 if(dir != MODE_ADD)
1072 {
1073 *mbuf++ = '+';
1074 dir = MODE_ADD;
1075 }
1076 *mbuf++ = 'j';
1077 len = rb_sprintf(pbuf, "%d:%d ", mode->join_num, mode->join_time);
1078 pbuf += len;
1079 }
1080 if(mode->forward[0] && strcmp(oldmode->forward, mode->forward) && ConfigChannel.use_forward)
1081 {
1082 if(dir != MODE_ADD)
1083 {
1084 *mbuf++ = '+';
1085 dir = MODE_ADD;
1086 }
1087 *mbuf++ = 'f';
1088 len = rb_sprintf(pbuf, "%s ", mode->forward);
1089 pbuf += len;
1090 }
1091 *mbuf = '\0';
1092 }
1093
1094 /*
1095 * remove_our_modes
1096 *
1097 * inputs -
1098 * output -
1099 * side effects -
1100 */
1101 static void
1102 remove_our_modes(struct Channel *chptr, struct Client *source_p)
1103 {
1104 struct membership *msptr;
1105 rb_dlink_node *ptr;
1106 char lmodebuf[MODEBUFLEN];
1107 char *lpara[MAXMODEPARAMS];
1108 int count = 0;
1109 int i;
1110
1111 mbuf = lmodebuf;
1112 *mbuf++ = '-';
1113
1114 for(i = 0; i < MAXMODEPARAMS; i++)
1115 lpara[i] = NULL;
1116
1117 RB_DLINK_FOREACH(ptr, chptr->members.head)
1118 {
1119 msptr = ptr->data;
1120
1121 if(is_chanop(msptr))
1122 {
1123 msptr->flags &= ~CHFL_CHANOP;
1124 lpara[count++] = msptr->client_p->name;
1125 *mbuf++ = 'o';
1126
1127 /* +ov, might not fit so check. */
1128 if(is_voiced(msptr))
1129 {
1130 if(count >= MAXMODEPARAMS)
1131 {
1132 *mbuf = '\0';
1133 sendto_channel_local(ALL_MEMBERS, chptr,
1134 ":%s MODE %s %s %s %s %s %s",
1135 source_p->name, chptr->chname,
1136 lmodebuf, lpara[0], lpara[1],
1137 lpara[2], lpara[3]);
1138
1139 /* preserve the initial '-' */
1140 mbuf = lmodebuf;
1141 *mbuf++ = '-';
1142 count = 0;
1143
1144 for(i = 0; i < MAXMODEPARAMS; i++)
1145 lpara[i] = NULL;
1146 }
1147
1148 msptr->flags &= ~CHFL_VOICE;
1149 lpara[count++] = msptr->client_p->name;
1150 *mbuf++ = 'v';
1151 }
1152 }
1153 else if(is_voiced(msptr))
1154 {
1155 msptr->flags &= ~CHFL_VOICE;
1156 lpara[count++] = msptr->client_p->name;
1157 *mbuf++ = 'v';
1158 }
1159 else
1160 continue;
1161
1162 if(count >= MAXMODEPARAMS)
1163 {
1164 *mbuf = '\0';
1165 sendto_channel_local(ALL_MEMBERS, chptr,
1166 ":%s MODE %s %s %s %s %s %s",
1167 source_p->name, chptr->chname, lmodebuf,
1168 lpara[0], lpara[1], lpara[2], lpara[3]);
1169 mbuf = lmodebuf;
1170 *mbuf++ = '-';
1171 count = 0;
1172
1173 for(i = 0; i < MAXMODEPARAMS; i++)
1174 lpara[i] = NULL;
1175 }
1176 }
1177
1178 if(count != 0)
1179 {
1180 *mbuf = '\0';
1181 sendto_channel_local(ALL_MEMBERS, chptr,
1182 ":%s MODE %s %s %s %s %s %s",
1183 source_p->name, chptr->chname, lmodebuf,
1184 EmptyString(lpara[0]) ? "" : lpara[0],
1185 EmptyString(lpara[1]) ? "" : lpara[1],
1186 EmptyString(lpara[2]) ? "" : lpara[2],
1187 EmptyString(lpara[3]) ? "" : lpara[3]);
1188
1189 }
1190 }
1191
1192 /* remove_ban_list()
1193 *
1194 * inputs - channel, source, list to remove, char of mode, caps needed
1195 * outputs -
1196 * side effects - given list is removed, with modes issued to local clients
1197 */
1198 static void
1199 remove_ban_list(struct Channel *chptr, struct Client *source_p,
1200 rb_dlink_list * list, char c, int mems)
1201 {
1202 static char lmodebuf[BUFSIZE];
1203 static char lparabuf[BUFSIZE];
1204 struct Ban *banptr;
1205 rb_dlink_node *ptr;
1206 rb_dlink_node *next_ptr;
1207 char *pbuf;
1208 int count = 0;
1209 int cur_len, mlen, plen;
1210
1211 pbuf = lparabuf;
1212
1213 cur_len = mlen = rb_sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
1214 mbuf = lmodebuf + mlen;
1215
1216 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
1217 {
1218 banptr = ptr->data;
1219
1220 /* trailing space, and the mode letter itself */
1221 plen = strlen(banptr->banstr) + 2;
1222
1223 if(count >= MAXMODEPARAMS || (cur_len + plen) > BUFSIZE - 4)
1224 {
1225 /* remove trailing space */
1226 *mbuf = '\0';
1227 *(pbuf - 1) = '\0';
1228
1229 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
1230
1231 cur_len = mlen;
1232 mbuf = lmodebuf + mlen;
1233 pbuf = lparabuf;
1234 count = 0;
1235 }
1236
1237 *mbuf++ = c;
1238 cur_len += plen;
1239 pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr);
1240 count++;
1241
1242 free_ban(banptr);
1243 }
1244
1245 *mbuf = '\0';
1246 *(pbuf - 1) = '\0';
1247 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
1248
1249 list->head = list->tail = NULL;
1250 list->length = 0;
1251 }