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