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