]> jfr.im git - irc/rqf/shadowircd.git/blob - modules/core/m_join.c
82d5d708f2a27120f778dda9c0d7712c03e656e5
[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 * Don't kick if the source has sent EOB (services
398 * deopping everyone by TS-1 SJOIN).
399 * -- jilles */
400 if (ConfigChannel.kick_on_split_riding &&
401 !HasSentEob(source_p) &&
402 ((mode.mode & MODE_INVITEONLY) ||
403 (mode.key[0] != 0 && irccmp(mode.key, oldmode->key) != 0)))
404 {
405 struct membership *msptr;
406 struct Client *who;
407 int l = rb_dlink_list_length(&chptr->members);
408
409 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->locmembers.head)
410 {
411 msptr = ptr->data;
412 who = msptr->client_p;
413 sendto_one(who, ":%s KICK %s %s :Net Rider",
414 me.name, chptr->chname, who->name);
415
416 sendto_server(NULL, chptr, CAP_TS6, NOCAPS,
417 ":%s KICK %s %s :Net Rider",
418 me.id, chptr->chname,
419 who->id);
420 remove_user_from_channel(msptr);
421 if (--l == 0)
422 break;
423 }
424 if (l == 0)
425 {
426 /* Channel was emptied, create a new one */
427 if((chptr = get_or_create_channel(source_p, parv[2], &isnew)) == NULL)
428 return 0; /* oops! */
429
430 oldmode = &chptr->mode;
431 }
432 }
433 keep_our_modes = NO;
434 chptr->channelts = newts;
435 }
436 else
437 keep_new_modes = NO;
438
439 if(!keep_new_modes)
440 mode = *oldmode;
441 else if(keep_our_modes)
442 {
443 mode.mode |= oldmode->mode;
444 if(oldmode->limit > mode.limit)
445 mode.limit = oldmode->limit;
446 if(strcmp(mode.key, oldmode->key) < 0)
447 strcpy(mode.key, oldmode->key);
448 if(oldmode->join_num > mode.join_num ||
449 (oldmode->join_num == mode.join_num &&
450 oldmode->join_time > mode.join_time))
451 {
452 mode.join_num = oldmode->join_num;
453 mode.join_time = oldmode->join_time;
454 }
455 if(irccmp(mode.forward, oldmode->forward) < 0)
456 strcpy(mode.forward, oldmode->forward);
457 }
458 else
459 {
460 /* If setting -j, clear join throttle state -- jilles */
461 if (!mode.join_num)
462 chptr->join_count = chptr->join_delta = 0;
463 }
464
465 set_final_mode(&mode, oldmode);
466 chptr->mode = mode;
467
468 /* Lost the TS, other side wins, so remove modes on this side */
469 if(!keep_our_modes)
470 {
471 remove_our_modes(chptr, fakesource_p);
472 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
473 {
474 del_invite(chptr, ptr->data);
475 }
476
477 if(rb_dlink_list_length(&chptr->banlist) > 0)
478 remove_ban_list(chptr, fakesource_p, &chptr->banlist, 'b', ALL_MEMBERS);
479 if(rb_dlink_list_length(&chptr->exceptlist) > 0)
480 remove_ban_list(chptr, fakesource_p, &chptr->exceptlist,
481 'e', ONLY_CHANOPS);
482 if(rb_dlink_list_length(&chptr->invexlist) > 0)
483 remove_ban_list(chptr, fakesource_p, &chptr->invexlist,
484 'I', ONLY_CHANOPS);
485 if(rb_dlink_list_length(&chptr->quietlist) > 0)
486 remove_ban_list(chptr, fakesource_p, &chptr->quietlist,
487 'q', ALL_MEMBERS);
488 chptr->bants++;
489
490 sendto_channel_local(ALL_MEMBERS, chptr,
491 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
492 me.name, chptr->chname, chptr->chname,
493 (long) oldts, (long) newts);
494 /* Update capitalization in channel name, this makes the
495 * capitalization timestamped like modes are -- jilles */
496 strcpy(chptr->chname, parv[2]);
497
498 /* since we're dropping our modes, we want to clear the mlock as well. --nenolod */
499 set_channel_mlock(client_p, source_p, chptr, NULL, FALSE);
500 }
501
502 if(*modebuf != '\0')
503 sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
504 fakesource_p->name, chptr->chname, modebuf, parabuf);
505
506 if(*omodebuf != '\0')
507 sendto_channel_local(ONLY_OPERS, chptr, ":%s MODE %s %s %s",
508 fakesource_p->name, chptr->chname, omodebuf, parabuf);
509
510 *omodebuf = *modebuf = *parabuf = '\0';
511
512 if(parv[3][0] != '0' && keep_new_modes)
513 modes = channel_modes(chptr, source_p);
514 else
515 modes = empty_modes;
516
517 mlen_uid = rb_sprintf(buf_uid, ":%s SJOIN %ld %s %s :",
518 use_id(source_p), (long) chptr->channelts, parv[2], modes);
519 ptr_uid = buf_uid + mlen_uid;
520
521 mbuf = modebuf;
522 ombuf = omodebuf;
523 para[0] = para[1] = para[2] = para[3] = empty;
524 pargs = 0;
525 len_nick = len_uid = 0;
526
527 /* if theres a space, theres going to be more than one nick, change the
528 * first space to \0, so s is just the first nick, and point p to the
529 * second nick
530 */
531 if((p = strchr(s, ' ')) != NULL)
532 {
533 *p++ = '\0';
534 }
535
536 *mbuf++ = '+';
537
538 while (s)
539 {
540 fl = 0;
541
542 for (i = 0; i < 4; i++)
543 {
544 if(*s == '!')
545 {
546 fl |= CHFL_ADMIN;
547 s++;
548 }
549 else if(*s == '@')
550 {
551 fl |= CHFL_CHANOP;
552 s++;
553 }
554 else if(*s == '%')
555 {
556 fl |= CHFL_HALFOP;
557 s++;
558 }
559 else if(*s == '+')
560 {
561 fl |= CHFL_VOICE;
562 s++;
563 }
564 }
565
566 /* if the client doesnt exist or is fake direction, skip. */
567 if(!(target_p = find_client(s)) ||
568 (target_p->from != client_p) || !IsPerson(target_p))
569 goto nextnick;
570
571 /* we assume for these we can fit at least one nick/uid in.. */
572
573 /* check we can fit another status+nick+space into a buffer */
574 if((mlen_uid + len_uid + IDLEN + 3) > (BUFSIZE - 3))
575 {
576 *(ptr_uid - 1) = '\0';
577 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
578 ptr_uid = buf_uid + mlen_uid;
579 len_uid = 0;
580 }
581
582 if(keep_new_modes)
583 {
584 if(fl & CHFL_ADMIN)
585 {
586 *ptr_uid++ = '!';
587 len_nick++;
588 len_uid++;
589 }
590 if(fl & CHFL_CHANOP)
591 {
592 *ptr_uid++ = '@';
593 len_nick++;
594 len_uid++;
595 }
596 if(fl & CHFL_HALFOP)
597 {
598 *ptr_uid++ = '%';
599 len_nick++;
600 len_uid++;
601 }
602 if(fl & CHFL_VOICE)
603 {
604 *ptr_uid++ = '+';
605 len_nick++;
606 len_uid++;
607 }
608 }
609
610 /* copy the nick to the two buffers */
611 len = rb_sprintf(ptr_uid, "%s ", use_id(target_p));
612 ptr_uid += len;
613 len_uid += len;
614
615 if(!keep_new_modes)
616 fl = 0;
617
618 if(!IsMember(target_p, chptr))
619 {
620 add_user_to_channel(chptr, target_p, fl);
621 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
622 target_p->name,
623 target_p->username, target_p->host, parv[2]);
624 joins++;
625 }
626
627 /* If anyone can think of a way to do this that doesn't make babies cry
628 * I would love to hear it - Taros */
629
630 if(fl & CHFL_ADMIN)
631 {
632 *mbuf++ = 'a';
633 para[pargs++] = target_p->name;
634
635 if(fl & CHFL_CHANOP)
636 {
637 /* its possible the +a has filled up MAXMODEPARAMS, if so, start
638 * a new buffer
639 */
640 if(pargs >= MAXMODEPARAMS)
641 {
642 *mbuf = '\0';
643 sendto_channel_local(ALL_MEMBERS, chptr,
644 ":%s MODE %s %s %s %s %s %s",
645 fakesource_p->name, chptr->chname,
646 modebuf,
647 para[0], para[1], para[2], para[3]);
648 mbuf = modebuf;
649 *mbuf++ = '+';
650 para[0] = para[1] = para[2] = para[3] = NULL;
651 pargs = 0;
652 }
653
654 *mbuf++ = 'o';
655 para[pargs++] = target_p->name;
656 }
657 if(fl & CHFL_HALFOP)
658 {
659 /* its possible the +a has filled up MAXMODEPARAMS, if so, start
660 * a new buffer
661 */
662 if(pargs >= MAXMODEPARAMS)
663 {
664 *mbuf = '\0';
665 sendto_channel_local(ALL_MEMBERS, chptr,
666 ":%s MODE %s %s %s %s %s %s",
667 fakesource_p->name, chptr->chname,
668 modebuf,
669 para[0], para[1], para[2], para[3]);
670 mbuf = modebuf;
671 *mbuf++ = '+';
672 para[0] = para[1] = para[2] = para[3] = NULL;
673 pargs = 0;
674 }
675
676 *mbuf++ = 'h';
677 para[pargs++] = target_p->name;
678 }
679 if(fl & CHFL_VOICE)
680 {
681 /* its possible the +a has filled up MAXMODEPARAMS, if so, start
682 * a new buffer
683 */
684 if(pargs >= MAXMODEPARAMS)
685 {
686 *mbuf = '\0';
687 sendto_channel_local(ALL_MEMBERS, chptr,
688 ":%s MODE %s %s %s %s %s %s",
689 fakesource_p->name, chptr->chname,
690 modebuf,
691 para[0], para[1], para[2], para[3]);
692 mbuf = modebuf;
693 *mbuf++ = '+';
694 para[0] = para[1] = para[2] = para[3] = NULL;
695 pargs = 0;
696 }
697
698 *mbuf++ = 'v';
699 para[pargs++] = target_p->name;
700 }
701 }
702 else if(fl & CHFL_CHANOP)
703 {
704 *mbuf++ = 'o';
705 para[pargs++] = target_p->name;
706
707 if(fl & CHFL_HALFOP)
708 {
709 /* its possible the +o has filled up MAXMODEPARAMS, if so, start
710 * a new buffer
711 */
712 if(pargs >= MAXMODEPARAMS)
713 {
714 *mbuf = '\0';
715 sendto_channel_local(ALL_MEMBERS, chptr,
716 ":%s MODE %s %s %s %s %s %s",
717 fakesource_p->name, chptr->chname,
718 modebuf,
719 para[0], para[1], para[2], para[3]);
720 mbuf = modebuf;
721 *mbuf++ = '+';
722 para[0] = para[1] = para[2] = para[3] = NULL;
723 pargs = 0;
724 }
725
726 *mbuf++ = 'h';
727 para[pargs++] = target_p->name;
728 }
729 if(fl & CHFL_VOICE)
730 {
731 /* its possible the +o has filled up MAXMODEPARAMS, if so, start
732 * a new buffer
733 */
734 if(pargs >= MAXMODEPARAMS)
735 {
736 *mbuf = '\0';
737 sendto_channel_local(ALL_MEMBERS, chptr,
738 ":%s MODE %s %s %s %s %s %s",
739 fakesource_p->name, chptr->chname,
740 modebuf,
741 para[0], para[1], para[2], para[3]);
742 mbuf = modebuf;
743 *mbuf++ = '+';
744 para[0] = para[1] = para[2] = para[3] = NULL;
745 pargs = 0;
746 }
747
748 *mbuf++ = 'v';
749 para[pargs++] = target_p->name;
750 }
751 }
752 else if(fl & CHFL_HALFOP)
753 {
754 *mbuf++ = 'h';
755 para[pargs++] = target_p->name;
756
757 if(fl & CHFL_VOICE)
758 {
759 /* its possible the +h has filled up MAXMODEPARAMS, if so, start
760 * a new buffer
761 */
762 if(pargs >= MAXMODEPARAMS)
763 {
764 *mbuf = '\0';
765 sendto_channel_local(ALL_MEMBERS, chptr,
766 ":%s MODE %s %s %s %s %s %s",
767 fakesource_p->name, chptr->chname,
768 modebuf,
769 para[0], para[1], para[2], para[3]);
770 mbuf = modebuf;
771 *mbuf++ = '+';
772 para[0] = para[1] = para[2] = para[3] = NULL;
773 pargs = 0;
774 }
775
776 *mbuf++ = 'v';
777 para[pargs++] = target_p->name;
778 }
779 }
780 else if(fl & CHFL_VOICE)
781 {
782 *mbuf++ = 'v';
783 para[pargs++] = target_p->name;
784 }
785
786 if(pargs >= MAXMODEPARAMS)
787 {
788 *mbuf = '\0';
789 sendto_channel_local(ALL_MEMBERS, chptr,
790 ":%s MODE %s %s %s %s %s %s",
791 fakesource_p->name,
792 chptr->chname,
793 modebuf, para[0], para[1], para[2], para[3]);
794 mbuf = modebuf;
795 *mbuf++ = '+';
796 para[0] = para[1] = para[2] = para[3] = NULL;
797 pargs = 0;
798 }
799
800 nextnick:
801 /* p points to the next nick */
802 s = p;
803
804 /* if there was a trailing space and p was pointing to it, then we
805 * need to exit.. this has the side effect of breaking double spaces
806 * in an sjoin.. but that shouldnt happen anyway
807 */
808 if(s && (*s == '\0'))
809 s = p = NULL;
810
811 /* if p was NULL due to no spaces, s wont exist due to the above, so
812 * we cant check it for spaces.. if there are no spaces, then when
813 * we next get here, s will be NULL
814 */
815 if(s && ((p = strchr(s, ' ')) != NULL))
816 {
817 *p++ = '\0';
818 }
819 }
820
821 *mbuf = '\0';
822 if(pargs)
823 {
824 sendto_channel_local(ALL_MEMBERS, chptr,
825 ":%s MODE %s %s %s %s %s %s",
826 fakesource_p->name, chptr->chname, modebuf,
827 para[0], CheckEmpty(para[1]),
828 CheckEmpty(para[2]), CheckEmpty(para[3]));
829 }
830
831 if(!joins && !(chptr->mode.mode & MODE_PERMANENT) && isnew)
832 {
833 destroy_channel(chptr);
834
835 return 0;
836 }
837
838 /* Keep the colon if we're sending an SJOIN without nicks -- jilles */
839 if (joins)
840 {
841 *(ptr_uid - 1) = '\0';
842 }
843
844 sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
845
846 return 0;
847 }
848
849
850 static void
851 set_final_mode(struct Mode *mode, struct Mode *oldmode)
852 {
853 int dir = MODE_QUERY, odir = MODE_QUERY;
854 char *pbuf = parabuf;
855 int len;
856 int i;
857
858 /* ok, first get a list of modes we need to add */
859 for (i = 0; i < 256; i++)
860 {
861 if((mode->mode & chmode_flags[i]) && !(oldmode->mode & chmode_flags[i]))
862 {
863 if (chmode_table[i].set_func == chm_hidden)
864 {
865 if(odir != MODE_ADD)
866 {
867 *ombuf++ = '+';
868 odir = MODE_ADD;
869 }
870 *ombuf++ = i;
871 }
872 else
873 {
874 if(dir != MODE_ADD)
875 {
876 *mbuf++ = '+';
877 dir = MODE_ADD;
878 }
879 *mbuf++ = i;
880
881 }
882 }
883 }
884
885 /* now the ones we need to remove. */
886 for (i = 0; i < 256; i++)
887 {
888 if((oldmode->mode & chmode_flags[i]) && !(mode->mode & chmode_flags[i]))
889 {
890 if(chmode_table[i].set_func == chm_hidden)
891 {
892 if(odir != MODE_DEL)
893 {
894 *ombuf++ = '-';
895 odir = MODE_DEL;
896 }
897 *ombuf++ = i;
898 }
899 else
900 {
901 if(dir != MODE_DEL)
902 {
903 *mbuf++ = '-';
904 dir = MODE_DEL;
905 }
906 *mbuf++ = i;
907 }
908 }
909 }
910
911 if(oldmode->limit && !mode->limit)
912 {
913 if(dir != MODE_DEL)
914 {
915 *mbuf++ = '-';
916 dir = MODE_DEL;
917 }
918 *mbuf++ = 'l';
919 }
920 if(oldmode->key[0] && !mode->key[0])
921 {
922 if(dir != MODE_DEL)
923 {
924 *mbuf++ = '-';
925 dir = MODE_DEL;
926 }
927 *mbuf++ = 'k';
928 len = rb_sprintf(pbuf, "%s ", oldmode->key);
929 pbuf += len;
930 }
931 if(oldmode->join_num && !mode->join_num)
932 {
933 if(dir != MODE_DEL)
934 {
935 *mbuf++ = '-';
936 dir = MODE_DEL;
937 }
938 *mbuf++ = 'j';
939 }
940 if(oldmode->forward[0] && !mode->forward[0])
941 {
942 if(dir != MODE_DEL)
943 {
944 *mbuf++ = '-';
945 dir = MODE_DEL;
946 }
947 *mbuf++ = 'f';
948 }
949 if(mode->limit && oldmode->limit != mode->limit)
950 {
951 if(dir != MODE_ADD)
952 {
953 *mbuf++ = '+';
954 dir = MODE_ADD;
955 }
956 *mbuf++ = 'l';
957 len = rb_sprintf(pbuf, "%d ", mode->limit);
958 pbuf += len;
959 }
960 if(mode->key[0] && strcmp(oldmode->key, mode->key))
961 {
962 if(dir != MODE_ADD)
963 {
964 *mbuf++ = '+';
965 dir = MODE_ADD;
966 }
967 *mbuf++ = 'k';
968 len = rb_sprintf(pbuf, "%s ", mode->key);
969 pbuf += len;
970 }
971 if(mode->join_num && (oldmode->join_num != mode->join_num || oldmode->join_time != mode->join_time))
972 {
973 if(dir != MODE_ADD)
974 {
975 *mbuf++ = '+';
976 dir = MODE_ADD;
977 }
978 *mbuf++ = 'j';
979 len = rb_sprintf(pbuf, "%d:%d ", mode->join_num, mode->join_time);
980 pbuf += len;
981 }
982 if(mode->forward[0] && strcmp(oldmode->forward, mode->forward) && ConfigChannel.use_forward)
983 {
984 if(dir != MODE_ADD)
985 {
986 *mbuf++ = '+';
987 dir = MODE_ADD;
988 }
989 *mbuf++ = 'f';
990 len = rb_sprintf(pbuf, "%s ", mode->forward);
991 pbuf += len;
992 }
993 *mbuf = '\0';
994 }
995
996 /*
997 * remove_our_modes
998 *
999 * inputs -
1000 * output -
1001 * side effects -
1002 */
1003 static void
1004 remove_our_modes(struct Channel *chptr, struct Client *source_p)
1005 {
1006 struct membership *msptr;
1007 rb_dlink_node *ptr;
1008 char lmodebuf[MODEBUFLEN];
1009 char *lpara[MAXMODEPARAMS];
1010 int count = 0;
1011 int i;
1012
1013 mbuf = lmodebuf;
1014 *mbuf++ = '-';
1015
1016 for(i = 0; i < MAXMODEPARAMS; i++)
1017 lpara[i] = NULL;
1018
1019 RB_DLINK_FOREACH(ptr, chptr->members.head)
1020 {
1021 msptr = ptr->data;
1022
1023 /* If anyone can think of a way to do this that doesn't make babies cry
1024 * I would love to hear it - Taros */
1025
1026 if(is_admin(msptr))
1027 {
1028 msptr->flags &= ~CHFL_ADMIN;
1029 lpara[count++] = msptr->client_p->name;
1030 *mbuf++ = 'a';
1031
1032 /* Make sure it fits if +h, +o, or +v are involved */
1033 if(is_chanop(msptr))
1034 {
1035 if(count >= MAXMODEPARAMS)
1036 {
1037 *mbuf = '\0';
1038 sendto_channel_local(ALL_MEMBERS, chptr,
1039 ":%s MODE %s %s %s %s %s %s",
1040 source_p->name, chptr->chname,
1041 lmodebuf, lpara[0], lpara[1],
1042 lpara[2], lpara[3]);
1043
1044 /* preserve the initial '-' */
1045 mbuf = lmodebuf;
1046 *mbuf++ = '-';
1047 count = 0;
1048
1049 for(i = 0; i < MAXMODEPARAMS; i++)
1050 lpara[i] = NULL;
1051 }
1052
1053 msptr->flags &= ~CHFL_CHANOP;
1054 lpara[count++] = msptr->client_p->name;
1055 *mbuf++ = 'o';
1056 }
1057 if(is_halfop(msptr))
1058 {
1059 if(count >= MAXMODEPARAMS)
1060 {
1061 *mbuf = '\0';
1062 sendto_channel_local(ALL_MEMBERS, chptr,
1063 ":%s MODE %s %s %s %s %s %s",
1064 source_p->name, chptr->chname,
1065 lmodebuf, lpara[0], lpara[1],
1066 lpara[2], lpara[3]);
1067
1068 /* preserve the initial '-' */
1069 mbuf = lmodebuf;
1070 *mbuf++ = '-';
1071 count = 0;
1072
1073 for(i = 0; i < MAXMODEPARAMS; i++)
1074 lpara[i] = NULL;
1075 }
1076
1077 msptr->flags &= ~CHFL_HALFOP;
1078 lpara[count++] = msptr->client_p->name;
1079 *mbuf++ = 'h';
1080 }
1081 if(is_voiced(msptr))
1082 {
1083 if(count >= MAXMODEPARAMS)
1084 {
1085 *mbuf = '\0';
1086 sendto_channel_local(ALL_MEMBERS, chptr,
1087 ":%s MODE %s %s %s %s %s %s",
1088 source_p->name, chptr->chname,
1089 lmodebuf, lpara[0], lpara[1],
1090 lpara[2], lpara[3]);
1091
1092 /* preserve the initial '-' */
1093 mbuf = lmodebuf;
1094 *mbuf++ = '-';
1095 count = 0;
1096
1097 for(i = 0; i < MAXMODEPARAMS; i++)
1098 lpara[i] = NULL;
1099 }
1100
1101 msptr->flags &= ~CHFL_VOICE;
1102 lpara[count++] = msptr->client_p->name;
1103 *mbuf++ = 'v';
1104 }
1105 }
1106 else if(is_chanop(msptr))
1107 {
1108 msptr->flags &= ~CHFL_CHANOP;
1109 lpara[count++] = msptr->client_p->name;
1110 *mbuf++ = 'o';
1111
1112 /* Make sure it fits if +h or +v are involved */
1113 if(is_halfop(msptr))
1114 {
1115 if(count >= MAXMODEPARAMS)
1116 {
1117 *mbuf = '\0';
1118 sendto_channel_local(ALL_MEMBERS, chptr,
1119 ":%s MODE %s %s %s %s %s %s",
1120 source_p->name, chptr->chname,
1121 lmodebuf, lpara[0], lpara[1],
1122 lpara[2], lpara[3]);
1123
1124 /* preserve the initial '-' */
1125 mbuf = lmodebuf;
1126 *mbuf++ = '-';
1127 count = 0;
1128
1129 for(i = 0; i < MAXMODEPARAMS; i++)
1130 lpara[i] = NULL;
1131 }
1132
1133 msptr->flags &= ~CHFL_HALFOP;
1134 lpara[count++] = msptr->client_p->name;
1135 *mbuf++ = 'h';
1136 }
1137 if(is_voiced(msptr))
1138 {
1139 if(count >= MAXMODEPARAMS)
1140 {
1141 *mbuf = '\0';
1142 sendto_channel_local(ALL_MEMBERS, chptr,
1143 ":%s MODE %s %s %s %s %s %s",
1144 source_p->name, chptr->chname,
1145 lmodebuf, lpara[0], lpara[1],
1146 lpara[2], lpara[3]);
1147
1148 /* preserve the initial '-' */
1149 mbuf = lmodebuf;
1150 *mbuf++ = '-';
1151 count = 0;
1152
1153 for(i = 0; i < MAXMODEPARAMS; i++)
1154 lpara[i] = NULL;
1155 }
1156
1157 msptr->flags &= ~CHFL_VOICE;
1158 lpara[count++] = msptr->client_p->name;
1159 *mbuf++ = 'v';
1160 }
1161 }
1162 else if(is_halfop(msptr))
1163 {
1164 msptr->flags &= ~CHFL_HALFOP;
1165 lpara[count++] = msptr->client_p->name;
1166 *mbuf++ = 'h';
1167
1168 /* +hv, might not fit so check. */
1169 if(is_voiced(msptr))
1170 {
1171 if(count >= MAXMODEPARAMS)
1172 {
1173 *mbuf = '\0';
1174 sendto_channel_local(ALL_MEMBERS, chptr,
1175 ":%s MODE %s %s %s %s %s %s",
1176 source_p->name, chptr->chname,
1177 lmodebuf, lpara[0], lpara[1],
1178 lpara[2], lpara[3]);
1179
1180 /* preserve the initial '-' */
1181 mbuf = lmodebuf;
1182 *mbuf++ = '-';
1183 count = 0;
1184
1185 for(i = 0; i < MAXMODEPARAMS; i++)
1186 lpara[i] = NULL;
1187 }
1188
1189 msptr->flags &= ~CHFL_VOICE;
1190 lpara[count++] = msptr->client_p->name;
1191 *mbuf++ = 'v';
1192 }
1193 }
1194 else if(is_voiced(msptr))
1195 {
1196 msptr->flags &= ~CHFL_VOICE;
1197 lpara[count++] = msptr->client_p->name;
1198 *mbuf++ = 'v';
1199 }
1200 else
1201 continue;
1202
1203 if(count >= MAXMODEPARAMS)
1204 {
1205 *mbuf = '\0';
1206 sendto_channel_local(ALL_MEMBERS, chptr,
1207 ":%s MODE %s %s %s %s %s %s",
1208 source_p->name, chptr->chname, lmodebuf,
1209 lpara[0], lpara[1], lpara[2], lpara[3]);
1210 mbuf = lmodebuf;
1211 *mbuf++ = '-';
1212 count = 0;
1213
1214 for(i = 0; i < MAXMODEPARAMS; i++)
1215 lpara[i] = NULL;
1216 }
1217 }
1218
1219 if(count != 0)
1220 {
1221 *mbuf = '\0';
1222 sendto_channel_local(ALL_MEMBERS, chptr,
1223 ":%s MODE %s %s %s %s %s %s",
1224 source_p->name, chptr->chname, lmodebuf,
1225 EmptyString(lpara[0]) ? "" : lpara[0],
1226 EmptyString(lpara[1]) ? "" : lpara[1],
1227 EmptyString(lpara[2]) ? "" : lpara[2],
1228 EmptyString(lpara[3]) ? "" : lpara[3]);
1229
1230 }
1231 }
1232
1233 /* remove_ban_list()
1234 *
1235 * inputs - channel, source, list to remove, char of mode, caps needed
1236 * outputs -
1237 * side effects - given list is removed, with modes issued to local clients
1238 */
1239 static void
1240 remove_ban_list(struct Channel *chptr, struct Client *source_p,
1241 rb_dlink_list * list, char c, int mems)
1242 {
1243 static char lmodebuf[BUFSIZE];
1244 static char lparabuf[BUFSIZE];
1245 struct Ban *banptr;
1246 rb_dlink_node *ptr;
1247 rb_dlink_node *next_ptr;
1248 char *pbuf;
1249 int count = 0;
1250 int cur_len, mlen, plen;
1251
1252 pbuf = lparabuf;
1253
1254 cur_len = mlen = rb_sprintf(lmodebuf, ":%s MODE %s -", source_p->name, chptr->chname);
1255 mbuf = lmodebuf + mlen;
1256
1257 RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
1258 {
1259 banptr = ptr->data;
1260
1261 /* trailing space, and the mode letter itself */
1262 plen = strlen(banptr->banstr) + 2;
1263
1264 if(count >= MAXMODEPARAMS || (cur_len + plen) > BUFSIZE - 4)
1265 {
1266 /* remove trailing space */
1267 *mbuf = '\0';
1268 *(pbuf - 1) = '\0';
1269
1270 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
1271
1272 cur_len = mlen;
1273 mbuf = lmodebuf + mlen;
1274 pbuf = lparabuf;
1275 count = 0;
1276 }
1277
1278 *mbuf++ = c;
1279 cur_len += plen;
1280 pbuf += rb_sprintf(pbuf, "%s ", banptr->banstr);
1281 count++;
1282
1283 free_ban(banptr);
1284 }
1285
1286 *mbuf = '\0';
1287 *(pbuf - 1) = '\0';
1288 sendto_channel_local(mems, chptr, "%s %s", lmodebuf, lparabuf);
1289
1290 list->head = list->tail = NULL;
1291 list->length = 0;
1292 }