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