Author: Bleep <tomh@inxpress.net>
[ircu2.10.12-pk.git] / ircd / channel.c
1 /*
2  * IRC - Internet Relay Chat, ircd/channel.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Co Center
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 1, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "sys.h"
22 #include <stdlib.h>
23 #include "h.h"
24 #include "struct.h"
25 #include "channel.h"
26 #include "parse.h"
27 #include "whowas.h"
28 #include "send.h"
29 #include "s_err.h"
30 #include "numeric.h"
31 #include "ircd.h"
32 #include "common.h"
33 #include "match.h"
34 #include "list.h"
35 #include "hash.h"
36 #include "s_misc.h"
37 #include "s_user.h"
38 #include "s_conf.h"
39 #include "s_bsd.h"
40 #include "msg.h"
41 #include "common.h"
42 #include "s_serv.h"
43 #include "channel.h"
44 #include "support.h"
45 #include "numnicks.h"
46 #include "sprintf_irc.h"
47 #include "querycmds.h"
48
49 RCSTAG_CC("$Id$");
50
51 aChannel *channel = NullChn;
52
53 static void sendmodeto_one(aClient *cptr, char *from, char *name,
54     char *mode, char *param, time_t creationtime);
55 static void add_invite(aClient *, aChannel *);
56 static int add_banid(aClient *, aChannel *, char *, int, int);
57 static Link *next_overlapped_ban(void);
58 static Link *next_removed_overlapped_ban(void);
59 static int can_join(aClient *, aChannel *, char *);
60 static void channel_modes(aClient *, char *, char *, aChannel *);
61 static int del_banid(aChannel *, char *, int);
62 static int is_banned(aClient *, aChannel *, Link *);
63 static int number_of_zombies(aChannel *);
64 static int is_deopped(aClient *, aChannel *);
65 static int set_mode(aClient *, aClient *, aChannel *, int,
66     char **, char *, char *, char *, int *);
67 static void sub1_from_channel(aChannel *);
68 static void send_hack_notice(aClient *, aClient *, int, char *[], int, int);
69 static void clean_channelname(char *);
70
71 void del_invite(aClient *, aChannel *);
72
73 static char *PartFmt1 = ":%s PART %s";
74 static char *PartFmt2 = ":%s PART %s :%s";
75 /*
76  * some buffers for rebuilding channel/nick lists with ,'s
77  */
78 static char nickbuf[BUFSIZE], buf[BUFSIZE];
79 static char modebuf[MODEBUFLEN], parabuf[MODEBUFLEN];
80 static char nparabuf[MODEBUFLEN];
81
82 /*
83  * Maximum acceptable lag time in seconds: A channel younger than
84  * this is not protected against hacking admins.
85  * Mainly here to check if the TS clocks really sync (otherwise this
86  * will start causing HACK notices.
87  * This value must be the same on all servers.
88  *
89  * This value has been increased to 1 day in order to distinguish this
90  * "normal" type of HACK wallops / desyncs, from possiblity still
91  * existing bugs.
92  */
93 #define TS_LAG_TIME ((time_t)86400)
94
95 /*
96  * A Magic TS that is used for channels that are created by JOIN,
97  * a channel with this TS accepts all TS without complaining that
98  * it might receive later via MODE or CREATE.
99  */
100 #define MAGIC_REMOTE_JOIN_TS 1270080000
101
102 /*
103  * Use a global variable to remember if an oper set a mode on a local channel. Ugly,
104  * but the only way to do it without changing set_mode intensively.
105  */
106 int LocalChanOperMode = 0;
107
108 /*
109  * return the length (>=0) of a chain of links.
110  */
111 static int list_length(Link *lp)
112 {
113   Reg2 int count = 0;
114
115   for (; lp; lp = lp->next)
116     count++;
117   return count;
118 }
119
120 /*
121  * find_chasing
122  *
123  * Find the client structure for a nick name (user) using history
124  * mechanism if necessary. If the client is not found, an error
125  * message (NO SUCH NICK) is generated. If the client was found
126  * through the history, chasing will be 1 and otherwise 0.
127  */
128 static aClient *find_chasing(aClient *sptr, char *user, int *chasing)
129 {
130   Reg2 aClient *who = FindClient(user);
131
132   if (chasing)
133     *chasing = 0;
134   if (who)
135     return who;
136   if (!(who = get_history(user, (long)KILLCHASETIMELIMIT)))
137   {
138     sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, sptr->name, user);
139     return NULL;
140   }
141   if (chasing)
142     *chasing = 1;
143   return who;
144 }
145
146 /*
147  * Create a string of form "foo!bar@fubar" given foo, bar and fubar
148  * as the parameters.  If NULL, they become "*".
149  */
150 static char *make_nick_user_host(char *nick, char *name, char *host)
151 {
152   static char namebuf[NICKLEN + USERLEN + HOSTLEN + 3];
153   sprintf_irc(namebuf, "%s!%s@%s", nick, name, host);
154   return namebuf;
155 }
156
157 /*
158  * Create a string of form "foo!bar@123.456.789.123" given foo, bar and the
159  * IP-number as the parameters.  If NULL, they become "*".
160  */
161 static char *make_nick_user_ip(char *nick, char *name, struct in_addr ip)
162 {
163   static char ipbuf[NICKLEN + USERLEN + 16 + 3];
164   sprintf_irc(ipbuf, "%s!%s@%s", nick, name, inetntoa(ip));
165   return ipbuf;
166 }
167
168 /*
169  * add_banid
170  *
171  * `cptr' must be the client adding the ban.
172  *
173  * If `change' is true then add `banid' to channel `chptr'.
174  * Returns 0 if the ban was added.
175  * Returns -2 if the ban already existed and was marked CHFL_BURST_BAN_WIPEOUT.
176  * Return -1 otherwise.
177  *
178  * Those bans that overlapped with `banid' are flagged with CHFL_BAN_OVERLAPPED
179  * when `change' is false, otherwise they will be removed from the banlist.
180  * Subsequently calls to next_overlapped_ban() or next_removed_overlapped_ban()
181  * respectively will return these bans until NULL is returned.
182  *
183  * If `firsttime' is true, the ban list as returned by next_overlapped_ban()
184  * is reset (unless a non-zero value is returned, in which case the
185  * CHFL_BAN_OVERLAPPED flag might not have been reset!).
186  *
187  * --Run
188  */
189 static Link *next_ban, *prev_ban, *removed_bans_list;
190
191 static int add_banid(aClient *cptr, aChannel *chptr, char *banid,
192     int change, int firsttime)
193 {
194   Reg1 Link *ban, **banp;
195   Reg2 int cnt = 0, removed_bans = 0, len = strlen(banid);
196
197   if (firsttime)
198   {
199     next_ban = NULL;
200     if (prev_ban || removed_bans_list)
201       MyCoreDump;               /* Memory leak */
202   }
203   if (MyUser(cptr))
204     collapse(banid);
205   for (banp = &chptr->banlist; *banp;)
206   {
207     len += strlen((*banp)->value.ban.banstr);
208     ++cnt;
209     if (((*banp)->flags & CHFL_BURST_BAN_WIPEOUT))
210     {
211       if (!strcmp((*banp)->value.ban.banstr, banid))
212       {
213         (*banp)->flags &= ~CHFL_BURST_BAN_WIPEOUT;
214         return -2;
215       }
216     }
217     else if (!mmatch((*banp)->value.ban.banstr, banid))
218       return -1;
219     if (!mmatch(banid, (*banp)->value.ban.banstr))
220     {
221       Link *tmp = *banp;
222       if (change)
223       {
224         if (MyUser(cptr))
225         {
226           cnt--;
227           len -= strlen(tmp->value.ban.banstr);
228         }
229         *banp = tmp->next;
230 #if 0
231         /* Silently remove overlapping bans */
232         RunFree(tmp->value.ban.banstr);
233         RunFree(tmp->value.ban.who);
234         free_link(tmp);
235 #else
236         /* These will be sent to the user later as -b */
237         tmp->next = removed_bans_list;
238         removed_bans_list = tmp;
239         removed_bans = 1;
240 #endif
241       }
242       else if (!(tmp->flags & CHFL_BURST_BAN_WIPEOUT))
243       {
244         tmp->flags |= CHFL_BAN_OVERLAPPED;
245         if (!next_ban)
246           next_ban = tmp;
247         banp = &tmp->next;
248       }
249       else
250         banp = &tmp->next;
251     }
252     else
253     {
254       if (firsttime)
255         (*banp)->flags &= ~CHFL_BAN_OVERLAPPED;
256       banp = &(*banp)->next;
257     }
258   }
259   if (MyUser(cptr) && !removed_bans && (len > MAXBANLENGTH || (cnt >= MAXBANS)))
260   {
261     sendto_one(cptr, err_str(ERR_BANLISTFULL), me.name, cptr->name,
262         chptr->chname, banid);
263     return -1;
264   }
265   if (change)
266   {
267     char *ip_start;
268     ban = make_link();
269     ban->next = chptr->banlist;
270     ban->value.ban.banstr = (char *)RunMalloc(strlen(banid) + 1);
271     strcpy(ban->value.ban.banstr, banid);
272     ban->value.ban.who = (char *)RunMalloc(strlen(cptr->name) + 1);
273     strcpy(ban->value.ban.who, cptr->name);
274     ban->value.ban.when = now;
275     ban->flags = CHFL_BAN;      /* This bit is never used I think... */
276     if ((ip_start = strrchr(banid, '@')) && check_if_ipmask(ip_start + 1))
277       ban->flags |= CHFL_BAN_IPMASK;
278     chptr->banlist = ban;
279     /* Erase ban-valid-bit */
280     for (ban = chptr->members; ban; ban = ban->next)
281       ban->flags &= ~CHFL_BANVALID;     /* `ban' == channel member ! */
282   }
283   return 0;
284 }
285
286 static Link *next_overlapped_ban(void)
287 {
288   Reg1 Link *tmp = next_ban;
289   if (tmp)
290   {
291     Reg2 Link *ban;
292     for (ban = tmp->next; ban; ban = ban->next)
293       if ((ban->flags & CHFL_BAN_OVERLAPPED))
294         break;
295     next_ban = ban;
296   }
297   return tmp;
298 }
299
300 static Link *next_removed_overlapped_ban(void)
301 {
302   Reg1 Link *tmp = removed_bans_list;
303   if (prev_ban)
304   {
305     if (prev_ban->value.ban.banstr)     /* Can be set to NULL in set_mode() */
306       RunFree(prev_ban->value.ban.banstr);
307     RunFree(prev_ban->value.ban.who);
308     free_link(prev_ban);
309   }
310   if (tmp)
311     removed_bans_list = removed_bans_list->next;
312   prev_ban = tmp;
313   return tmp;
314 }
315
316 /*
317  * del_banid
318  *
319  * If `change' is true, delete `banid' from channel `chptr'.
320  * Returns `false' if removal was (or would have been) successful.
321  */
322 static int del_banid(aChannel *chptr, char *banid, int change)
323 {
324   Reg1 Link **ban;
325   Reg2 Link *tmp;
326
327   if (!banid)
328     return -1;
329   for (ban = &(chptr->banlist); *ban; ban = &((*ban)->next))
330     if (strCasediff(banid, (*ban)->value.ban.banstr) == 0)
331     {
332       tmp = *ban;
333       if (change)
334       {
335         *ban = tmp->next;
336         RunFree(tmp->value.ban.banstr);
337         RunFree(tmp->value.ban.who);
338         free_link(tmp);
339         /* Erase ban-valid-bit, for channel members that are banned */
340         for (tmp = chptr->members; tmp; tmp = tmp->next)
341           if ((tmp->flags & (CHFL_BANNED | CHFL_BANVALID)) ==
342               (CHFL_BANNED | CHFL_BANVALID))
343             tmp->flags &= ~CHFL_BANVALID;       /* `tmp' == channel member */
344       }
345       return 0;
346     }
347   return -1;
348 }
349
350 /*
351  * IsMember - returns Link * if a person is joined and not a zombie
352  */
353 Link *IsMember(aClient *cptr, aChannel *chptr)
354 {
355   Link *lp;
356   return (((lp = find_user_link(chptr->members, cptr)) &&
357       !(lp->flags & CHFL_ZOMBIE)) ? lp : NULL);
358 }
359
360 /*
361  * is_banned - a non-zero value if banned else 0.
362  */
363 static int is_banned(aClient *cptr, aChannel *chptr, Link *member)
364 {
365   Reg1 Link *tmp;
366   char *s, *ip_s = NULL;
367
368   if (!IsUser(cptr))
369     return 0;
370
371   if (member)
372   {
373     if ((member->flags & CHFL_BANVALID))
374       return (member->flags & CHFL_BANNED);
375   }
376
377   s = make_nick_user_host(cptr->name, cptr->user->username, cptr->user->host);
378
379   for (tmp = chptr->banlist; tmp; tmp = tmp->next)
380   {
381     if ((tmp->flags & CHFL_BAN_IPMASK))
382     {
383       if (!ip_s)
384         ip_s = make_nick_user_ip(cptr->name, cptr->user->username, cptr->ip);
385       if (match(tmp->value.ban.banstr, ip_s) == 0)
386         break;
387     }
388     else if (match(tmp->value.ban.banstr, s) == 0)
389       break;
390   }
391
392   if (member)
393   {
394     member->flags |= CHFL_BANVALID;
395     if (tmp)
396     {
397       member->flags |= CHFL_BANNED;
398       return 1;
399     }
400     else
401     {
402       member->flags &= ~CHFL_BANNED;
403       return 0;
404     }
405   }
406
407   return (tmp != NULL);
408 }
409
410 /*
411  * adds a user to a channel by adding another link to the channels member
412  * chain.
413  */
414 static void add_user_to_channel(aChannel *chptr, aClient *who, int flags)
415 {
416   Reg1 Link *ptr;
417
418   if (who->user)
419   {
420     ptr = make_link();
421     ptr->value.cptr = who;
422     ptr->flags = flags;
423     ptr->next = chptr->members;
424     chptr->members = ptr;
425     chptr->users++;
426
427     ptr = make_link();
428     ptr->value.chptr = chptr;
429     ptr->next = who->user->channel;
430     who->user->channel = ptr;
431     who->user->joined++;
432   }
433 }
434
435 void remove_user_from_channel(aClient *sptr, aChannel *chptr)
436 {
437   Reg1 Link **curr;
438   Reg2 Link *tmp;
439   Reg3 Link *lp = chptr->members;
440
441   for (; lp && (lp->flags & CHFL_ZOMBIE || lp->value.cptr == sptr);
442       lp = lp->next);
443   for (;;)
444   {
445     for (curr = &chptr->members; (tmp = *curr); curr = &tmp->next)
446       if (tmp->value.cptr == sptr)
447       {
448         *curr = tmp->next;
449         free_link(tmp);
450         break;
451       }
452     for (curr = &sptr->user->channel; (tmp = *curr); curr = &tmp->next)
453       if (tmp->value.chptr == chptr)
454       {
455         *curr = tmp->next;
456         free_link(tmp);
457         break;
458       }
459     sptr->user->joined--;
460     if (lp)
461       break;
462     if (chptr->members)
463       sptr = chptr->members->value.cptr;
464     else
465       break;
466     sub1_from_channel(chptr);
467   }
468   sub1_from_channel(chptr);
469 }
470
471 int is_chan_op(aClient *cptr, aChannel *chptr)
472 {
473   Reg1 Link *lp;
474
475   if (chptr)
476     if ((lp = find_user_link(chptr->members, cptr)) &&
477         !(lp->flags & CHFL_ZOMBIE))
478       return (lp->flags & CHFL_CHANOP);
479
480   return 0;
481 }
482
483 static int is_deopped(aClient *cptr, aChannel *chptr)
484 {
485   Reg1 Link *lp;
486
487   if (chptr)
488     if ((lp = find_user_link(chptr->members, cptr)))
489       return (lp->flags & CHFL_DEOPPED);
490
491   return (IsUser(cptr) ? 1 : 0);
492 }
493
494 int is_zombie(aClient *cptr, aChannel *chptr)
495 {
496   Reg1 Link *lp;
497
498   if (chptr)
499     if ((lp = find_user_link(chptr->members, cptr)))
500       return (lp->flags & CHFL_ZOMBIE);
501
502   return 0;
503 }
504
505 int has_voice(aClient *cptr, aChannel *chptr)
506 {
507   Reg1 Link *lp;
508
509   if (chptr)
510     if ((lp = find_user_link(chptr->members, cptr)) &&
511         !(lp->flags & CHFL_ZOMBIE))
512       return (lp->flags & CHFL_VOICE);
513
514   return 0;
515 }
516
517 int can_send(aClient *cptr, aChannel *chptr)
518 {
519   Reg1 Link *lp;
520
521   lp = IsMember(cptr, chptr);
522
523   if ((!lp || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE)) ||
524       (lp->flags & CHFL_ZOMBIE)) && MyUser(cptr) && is_banned(cptr, chptr, lp))
525     return (MODE_BAN);
526
527   if (chptr->mode.mode & MODE_MODERATED &&
528       (!lp || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE)) ||
529       (lp->flags & CHFL_ZOMBIE)))
530     return (MODE_MODERATED);
531
532   if (!lp && ((chptr->mode.mode & MODE_NOPRIVMSGS) ||
533       IsModelessChannel(chptr->chname)))
534     return (MODE_NOPRIVMSGS);
535
536   return 0;
537 }
538
539 /*
540  * write the "simple" list of channel modes for channel chptr onto buffer mbuf
541  * with the parameters in pbuf.
542  */
543 static void channel_modes(aClient *cptr, char *mbuf, char *pbuf,
544     aChannel *chptr)
545 {
546   *mbuf++ = '+';
547   if (chptr->mode.mode & MODE_SECRET)
548     *mbuf++ = 's';
549   else if (chptr->mode.mode & MODE_PRIVATE)
550     *mbuf++ = 'p';
551   if (chptr->mode.mode & MODE_MODERATED)
552     *mbuf++ = 'm';
553   if (chptr->mode.mode & MODE_TOPICLIMIT)
554     *mbuf++ = 't';
555   if (chptr->mode.mode & MODE_INVITEONLY)
556     *mbuf++ = 'i';
557   if (chptr->mode.mode & MODE_NOPRIVMSGS)
558     *mbuf++ = 'n';
559   if (chptr->mode.limit)
560   {
561     *mbuf++ = 'l';
562     sprintf_irc(pbuf, "%d", chptr->mode.limit);
563   }
564   if (*chptr->mode.key)
565   {
566     *mbuf++ = 'k';
567     if (is_chan_op(cptr, chptr) || IsServer(cptr))
568     {
569       if (chptr->mode.limit)
570         strcat(pbuf, " ");
571       strcat(pbuf, chptr->mode.key);
572     }
573   }
574   *mbuf = '\0';
575   return;
576 }
577
578 static int send_mode_list(aClient *cptr, char *chname, time_t creationtime,
579     Link *top, int mask, char flag)
580 {
581   Reg1 Link *lp;
582   Reg2 char *cp, *name;
583   int count = 0, send = 0, sent = 0;
584
585   cp = modebuf + strlen(modebuf);
586   if (*parabuf)                 /* mode +l or +k xx */
587     count = 1;
588   for (lp = top; lp; lp = lp->next)
589   {
590     if (!(lp->flags & mask))
591       continue;
592     if (mask == CHFL_BAN)
593       name = lp->value.ban.banstr;
594     else
595       name = lp->value.cptr->name;
596     if (strlen(parabuf) + strlen(name) + 11 < (size_t)MODEBUFLEN)
597     {
598       strcat(parabuf, " ");
599       strcat(parabuf, name);
600       count++;
601       *cp++ = flag;
602       *cp = '\0';
603     }
604     else if (*parabuf)
605       send = 1;
606     if (count == 6)
607       send = 1;
608     if (send)
609     {
610       /* cptr is always a server! So we send creationtimes */
611       sendmodeto_one(cptr, me.name, chname, modebuf, parabuf, creationtime);
612       sent = 1;
613       send = 0;
614       *parabuf = '\0';
615       cp = modebuf;
616       *cp++ = '+';
617       if (count != 6)
618       {
619         strcpy(parabuf, name);
620         *cp++ = flag;
621       }
622       count = 0;
623       *cp = '\0';
624     }
625   }
626   return sent;
627 }
628
629 /*
630  * send "cptr" a full list of the modes for channel chptr.
631  */
632 void send_channel_modes(aClient *cptr, aChannel *chptr)
633 {
634   int sent;
635   if (IsLocalChannel(chptr->chname))
636     return;
637
638   *modebuf = *parabuf = '\0';
639   channel_modes(cptr, modebuf, parabuf, chptr);
640
641   if (Protocol(cptr) < 10)
642   {
643     sent = send_mode_list(cptr, chptr->chname, chptr->creationtime,
644         chptr->members, CHFL_CHANOP, 'o');
645     if (!sent && chptr->creationtime)
646       sendto_one(cptr, ":%s MODE %s %s %s " TIME_T_FMT, me.name,
647           chptr->chname, modebuf, parabuf, chptr->creationtime);
648     else if (modebuf[1] || *parabuf)
649       sendmodeto_one(cptr, me.name,
650           chptr->chname, modebuf, parabuf, chptr->creationtime);
651
652     *parabuf = '\0';
653     *modebuf = '+';
654     modebuf[1] = '\0';
655     send_mode_list(cptr, chptr->chname, chptr->creationtime,
656         chptr->banlist, CHFL_BAN, 'b');
657     if (modebuf[1] || *parabuf)
658       sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
659           parabuf, chptr->creationtime);
660
661     *parabuf = '\0';
662     *modebuf = '+';
663     modebuf[1] = '\0';
664     send_mode_list(cptr, chptr->chname, chptr->creationtime,
665         chptr->members, CHFL_VOICE, 'v');
666     if (modebuf[1] || *parabuf)
667       sendmodeto_one(cptr, me.name, chptr->chname, modebuf,
668           parabuf, chptr->creationtime);
669   }
670   else
671   {
672     static unsigned int current_flags[4] =
673         { 0, CHFL_CHANOP | CHFL_VOICE, CHFL_VOICE, CHFL_CHANOP };
674     int first = 1, full = 1, flag_cnt = 0, new_mode = 0;
675     size_t len, sblen;
676     Link *lp1 = chptr->members;
677     Link *lp2 = chptr->banlist;
678     for (first = 1; full; first = 0)    /* Loop for multiple messages */
679     {
680       full = 0;                 /* Assume by default we get it
681                                    all in one message */
682
683       /* (Continued) prefix: "<Y> BURST <channel> <TS>" */
684       sprintf_irc(sendbuf, "%s BURST %s " TIME_T_FMT, NumServ(&me),
685           chptr->chname, chptr->creationtime);
686       sblen = strlen(sendbuf);
687
688       if (first && modebuf[1])  /* Add simple modes (iklmnpst)
689                                    if first message */
690       {
691         /* prefix: "<Y> BURST <channel> <TS>[ <modes>[ <params>]]" */
692         sendbuf[sblen++] = ' ';
693         strcpy(sendbuf + sblen, modebuf);
694         sblen += strlen(modebuf);
695         if (*parabuf)
696         {
697           sendbuf[sblen++] = ' ';
698           strcpy(sendbuf + sblen, parabuf);
699           sblen += strlen(parabuf);
700         }
701       }
702
703       /* Attach nicks, comma seperated " nick[:modes],nick[:modes],..." */
704       /* Run 4 times over all members, to group the members with the
705        * same mode together */
706       for (first = 1; flag_cnt < 4;
707           lp1 = chptr->members, new_mode = 1, flag_cnt++)
708       {
709         for (; lp1; lp1 = lp1->next)
710         {
711           if ((lp1->flags & (CHFL_CHANOP | CHFL_VOICE)) !=
712               current_flags[flag_cnt])
713             continue;           /* Skip members with different flags */
714           if (sblen + NUMNICKLEN + 4 > BUFSIZE - 3)
715             /* The 4 is a possible ",:ov"
716                The -3 is for the "\r\n\0" that is added in send.c */
717           {
718             full = 1;           /* Make sure we continue after
719                                    sending it so far */
720             break;              /* Do not add this member to this message */
721           }
722           sendbuf[sblen++] = first ? ' ' : ',';
723           first = 0;            /* From now on, us comma's to add new nicks */
724
725           sprintf_irc(sendbuf + sblen, "%s%s", NumNick(lp1->value.cptr));
726           sblen += strlen(sendbuf + sblen);
727
728           if (new_mode)         /* Do we have a nick with a new mode ? */
729           {
730             new_mode = 0;
731             sendbuf[sblen++] = ':';
732             if (lp1->flags & CHFL_CHANOP)
733               sendbuf[sblen++] = 'o';
734             if (lp1->flags & CHFL_VOICE)
735               sendbuf[sblen++] = 'v';
736           }
737         }
738         if (full)
739           break;
740       }
741
742       if (!full)
743       {
744         /* Attach all bans, space seperated " :%ban ban ..." */
745         for (first = 2; lp2; lp2 = lp2->next)
746         {
747           len = strlen(lp2->value.ban.banstr);
748           if (sblen + len + 1 + first > BUFSIZE - 3)
749             /* The +1 stands for the added ' '.
750              * The +first stands for the added ":%".
751              * The -3 is for the "\r\n\0" that is added in send.c
752              */
753           {
754             full = 1;
755             break;
756           }
757           if (first)
758           {
759             first = 0;
760             sendbuf[sblen++] = ' ';
761             sendbuf[sblen++] = ':';     /* Will be last parameter */
762             sendbuf[sblen++] = '%';     /* To tell bans apart */
763           }
764           else
765             sendbuf[sblen++] = ' ';
766           strcpy(sendbuf + sblen, lp2->value.ban.banstr);
767           sblen += len;
768         }
769       }
770
771       sendbuf[sblen] = '\0';
772       sendbufto_one(cptr);      /* Send this message */
773     }                           /* Continue when there was something
774                                    that didn't fit (full==1) */
775   }
776 }
777
778 /*
779  * m_mode
780  * parv[0] - sender
781  * parv[1] - channel
782  */
783
784 int m_mode(aClient *cptr, aClient *sptr, int parc, char *parv[])
785 {
786   int badop, sendts;
787   aChannel *chptr;
788
789   /* Now, try to find the channel in question */
790   if (parc > 1)
791   {
792     chptr = FindChannel(parv[1]);
793     if (chptr == NullChn)
794       return m_umode(cptr, sptr, parc, parv);
795   }
796   else
797   {
798     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "MODE");
799     return 0;
800   }
801
802   sptr->flags &= ~FLAGS_TS8;
803
804   if (MyUser(sptr))
805     clean_channelname(parv[1]);
806   else if (IsLocalChannel(parv[1]))
807     return 0;
808
809   /* sending an error wasnt good, lets just send an empty mode reply..  poptix */
810   if (IsModelessChannel(chptr->chname))
811   {
812     if (IsUser(sptr))
813       sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],
814           chptr->chname, "+nt", "");
815     return 0;
816   }
817
818   if (parc < 3)
819   {
820     *modebuf = *parabuf = '\0';
821     modebuf[1] = '\0';
822     channel_modes(sptr, modebuf, parabuf, chptr);
823     sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],
824         chptr->chname, modebuf, parabuf);
825     sendto_one(sptr, rpl_str(RPL_CREATIONTIME), me.name, parv[0],
826         chptr->chname, chptr->creationtime);
827     return 0;
828   }
829
830   LocalChanOperMode = 0;
831
832   if (!(sendts = set_mode(cptr, sptr, chptr, parc - 2, parv + 2,
833       modebuf, parabuf, nparabuf, &badop)))
834   {
835     sendto_one(sptr, err_str(IsMember(sptr, chptr) ? ERR_CHANOPRIVSNEEDED :
836         ERR_NOTONCHANNEL), me.name, parv[0], chptr->chname);
837     return 0;
838   }
839
840   if (badop >= 2)
841     send_hack_notice(cptr, sptr, parc, parv, badop, 1);
842
843   if (strlen(modebuf) > (size_t)1 || sendts > 0)
844   {
845     if (badop != 2 && strlen(modebuf) > (size_t)1)
846     {
847 #ifdef OPER_MODE_LCHAN
848       if (LocalChanOperMode) {
849          sendto_channel_butserv(chptr, &me, ":%s MODE %s %s %s",
850                                 me.name, chptr->chname, modebuf, parabuf);
851          sendto_op_mask(SNO_HACK4, 
852                         "OPER MODE: %s MODE %s %s %s",
853                         sptr->name,chptr->chname,modebuf,parabuf);
854        }
855        else
856 #endif
857       sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s",
858           parv[0], chptr->chname, modebuf, parabuf);
859     }
860     if (IsLocalChannel(chptr->chname))
861       return 0;
862     /* We send a creationtime of 0, to mark it as a hack --Run */
863     if (IsServer(sptr) && (badop == 2 || sendts > 0))
864     {
865       if (*modebuf == '\0')
866         strcpy(modebuf, "+");
867       if (badop != 2)
868       {
869         sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s %s " TIME_T_FMT,
870             parv[0], chptr->chname, modebuf, parabuf,
871             (badop == 4) ? (time_t) 0 : chptr->creationtime);
872         sendto_highprot_butone(cptr, 10, ":%s MODE %s %s %s " TIME_T_FMT,
873             parv[0], chptr->chname, modebuf, nparabuf,
874             (badop == 4) ? (time_t) 0 : chptr->creationtime);
875       }
876     }
877     else
878     {
879       sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s %s",
880           parv[0], chptr->chname, modebuf, parabuf);
881       sendto_highprot_butone(cptr, 10, ":%s MODE %s %s %s",
882           parv[0], chptr->chname, modebuf, nparabuf);
883     }
884   }
885   return 0;
886 }
887
888 static int DoesOp(char *modebuf)
889 {
890   modebuf--;                    /* Is it possible that a mode
891                                    starts with o and not +o ? */
892   while (*++modebuf)
893     if (*modebuf == 'o' || *modebuf == 'v')
894       return (1);
895   return 0;
896 }
897
898 /* This function should be removed when all servers are 2.10 */
899 static void sendmodeto_one(aClient *cptr, char *from, char *name,
900     char *mode, char *param, time_t creationtime)
901 {
902   if (IsServer(cptr) && DoesOp(mode) && creationtime)
903     sendto_one(cptr, ":%s MODE %s %s %s " TIME_T_FMT,
904         from, name, mode, param, creationtime);
905   else
906     sendto_one(cptr, ":%s MODE %s %s %s", from, name, mode, param);
907 }
908
909 /*
910  * pretty_mask
911  *
912  * by Carlo Wood (Run), 05 Oct 1998.
913  *
914  * Canonify a mask.
915  *
916  * When the nick is longer then NICKLEN, it is cut off (its an error of course).
917  * When the user name or host name are too long (USERLEN and HOSTLEN
918  * respectively) then they are cut off at the start with a '*'.
919  *
920  * The following transformations are made:
921  *
922  * 1)   xxx             -> nick!*@*
923  * 2)   xxx.xxx         -> *!*@host
924  * 3)   xxx!yyy         -> nick!user@*
925  * 4)   xxx@yyy         -> *!user@host
926  * 5)   xxx!yyy@zzz     -> nick!user@host
927  */
928 char *pretty_mask(char *mask)
929 {
930   static char star[2] = { '*', 0 };
931   char *last_dot = NULL;
932   char *ptr;
933
934   /* Case 1: default */
935   char *nick = mask;
936   char *user = star;
937   char *host = star;
938
939   /* Do a _single_ pass through the characters of the mask: */
940   for (ptr = mask; *ptr; ++ptr)
941   {
942     if (*ptr == '!')
943     {
944       /* Case 3 or 5: Found first '!' (without finding a '@' yet) */
945       user = ++ptr;
946       host = star;
947     }
948     else if (*ptr == '@')
949     {
950       /* Case 4: Found last '@' (without finding a '!' yet) */
951       nick = star;
952       user = mask;
953       host = ++ptr;
954     }
955     else if (*ptr == '.')
956     {
957       /* Case 2: Found last '.' (without finding a '!' or '@' yet) */
958       last_dot = ptr;
959       continue;
960     }
961     else
962       continue;
963     for (; *ptr; ++ptr)
964     {
965       if (*ptr == '@')
966       {
967         /* Case 4 or 5: Found last '@' */
968         host = ptr + 1;
969       }
970     }
971     break;
972   }
973   if (user == star && last_dot)
974   {
975     /* Case 2: */
976     nick = star;
977     user = star;
978     host = mask;
979   }
980   /* Check lengths */
981   if (nick != star)
982   {
983     char *nick_end = (user != star) ? user - 1 : ptr;
984     if (nick_end - nick > NICKLEN)
985       nick[NICKLEN] = 0;
986     *nick_end = 0;
987   }
988   if (user != star)
989   {
990     char *user_end = (host != star) ? host - 1 : ptr;
991     if (user_end - user > USERLEN)
992     {
993       user = user_end - USERLEN;
994       *user = '*';
995     }
996     *user_end = 0;
997   }
998   if (host != star && ptr - host > HOSTLEN)
999   {
1000     host = ptr - HOSTLEN;
1001     *host = '*';
1002   }
1003   return make_nick_user_host(nick, user, host);
1004 }
1005
1006 static char bmodebuf[MODEBUFLEN], bparambuf[MODEBUFLEN];
1007 static char nbparambuf[MODEBUFLEN];     /* "Numeric" Bounce Parameter Buffer */
1008
1009 /*
1010  * Check and try to apply the channel modes passed in the parv array for
1011  * the client ccptr to channel chptr.  The resultant changes are printed
1012  * into mbuf and pbuf (if any) and applied to the channel.
1013  */
1014 static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr, int parc,
1015     char *parv[], char *mbuf, char *pbuf, char *npbuf, int *badop)
1016 {
1017   static Link chops[MAXPARA - 2];       /* This size is only needed when a broken
1018                                            server sends more then MAXMODEPARAMS
1019                                            parameters */
1020   static int flags[] = {
1021     MODE_PRIVATE, 'p', MODE_SECRET, 's',
1022     MODE_MODERATED, 'm', MODE_NOPRIVMSGS, 'n',
1023     MODE_TOPICLIMIT, 't', MODE_INVITEONLY, 'i',
1024     MODE_VOICE, 'v', MODE_KEY, 'k',
1025     0x0, 0x0
1026   };
1027
1028   Reg1 Link *lp;
1029   Reg2 char *curr = parv[0], *cp = NULL;
1030   Reg3 int *ip;
1031   Link *member, *tmp = NULL;
1032   unsigned int whatt = MODE_ADD, bwhatt = 0;
1033   int limitset = 0, bounce, add_banid_called = 0;
1034   size_t len, nlen, blen, nblen;
1035   int keychange = 0;
1036   unsigned int nusers = 0, newmode;
1037   int opcnt = 0, banlsent = 0;
1038   int doesdeop = 0, doesop = 0, hacknotice = 0, change, gotts = 0;
1039   aClient *who;
1040   Mode *mode, oldm;
1041   static char numeric[16];
1042   char *bmbuf = bmodebuf, *bpbuf = bparambuf, *nbpbuf = nbparambuf;
1043   time_t newtime = (time_t) 0;
1044   aConfItem *aconf;
1045
1046   *mbuf = *pbuf = *npbuf = *bmbuf = *bpbuf = *nbpbuf = '\0';
1047   *badop = 0;
1048   if (parc < 1)
1049     return 0;
1050
1051   mode = &(chptr->mode);
1052   memcpy(&oldm, mode, sizeof(Mode));
1053   /*
1054    * Mode is accepted when sptr is a channel operator
1055    * but also when the mode is received from a server.
1056    * At this point, let any member pass, so they are allowed
1057    * to see the bans.
1058    */
1059   if (!(IsServer(cptr) || (tmp = IsMember(sptr, chptr))))
1060     return 0;
1061
1062 #ifdef OPER_MODE_LCHAN
1063   if (IsOperOnLocalChannel(sptr, chptr->chname) && !(tmp->flags & CHFL_CHANOP))
1064     LocalChanOperMode = 1;
1065 #endif
1066
1067   newmode = mode->mode;
1068
1069   while (curr && *curr)
1070   {
1071     switch (*curr)
1072     {
1073       case '+':
1074         whatt = MODE_ADD;
1075         break;
1076       case '-':
1077         whatt = MODE_DEL;
1078         break;
1079       case 'o':
1080       case 'v':
1081         if (--parc <= 0)
1082           break;
1083         parv++;
1084         if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1085           break;
1086         /*
1087          * Check for nickname changes and try to follow these
1088          * to make sure the right client is affected by the
1089          * mode change.
1090          * Even if we find a nick with find_chasing() there
1091          * is still a reason to ignore in a special case.
1092          * We need to ignore the mode when:
1093          * - It is part of a net.burst (from a server and
1094          *   a MODE_ADD). Ofcourse we don't ignore mode
1095          *   changes from Uworld.
1096          * - The found nick is not on the right side off
1097          *   the net.junction.
1098          * This fixes the bug that when someone (tries to)
1099          * ride a net.break and does so with the nick of
1100          * someone on the otherside, that he is nick collided
1101          * (killed) but his +o still ops the other person.
1102          */
1103         if (MyUser(sptr) || Protocol(cptr) < 10)
1104         {
1105           if (!(who = find_chasing(sptr, parv[0], NULL)))
1106             break;
1107         }
1108         else
1109         {
1110           if (!(who = findNUser(parv[0])))
1111             break;
1112         }
1113         if (whatt == MODE_ADD && IsServer(sptr) && who->from != sptr->from &&
1114             !find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))
1115           break;
1116         if (!(member = find_user_link(chptr->members, who)) ||
1117             (MyUser(sptr) && (member->flags & CHFL_ZOMBIE)))
1118         {
1119           sendto_one(cptr, err_str(ERR_USERNOTINCHANNEL),
1120               me.name, cptr->name, who->name, chptr->chname);
1121           break;
1122         }
1123         /* if the user is +k, prevent a deop from local user */
1124         if (whatt == MODE_DEL && IsChannelService(who) &&
1125             MyUser(cptr) && *curr == 'o')
1126         {
1127           sendto_one(cptr, err_str(ERR_ISCHANSERVICE), me.name,
1128               cptr->name, parv[0], chptr->chname);
1129           break;
1130         }
1131 #ifdef NO_OPER_DEOP_LCHAN
1132         /*
1133          * if the user is an oper on a local channel, prevent him
1134          * from being deoped. that oper can deop himself though.
1135          */
1136         if (whatt == MODE_DEL && IsOperOnLocalChannel(who, chptr->chname) && 
1137             (who != sptr) && MyUser(cptr) && *curr == 'o')
1138         {
1139           sendto_one(cptr, err_str(ERR_ISOPERLCHAN), me.name,
1140                      cptr->name, parv[0], chptr->chname);
1141           break;
1142         }
1143 #endif
1144         if (whatt == MODE_ADD)
1145         {
1146           lp = &chops[opcnt++];
1147           lp->value.cptr = who;
1148           if (IsServer(sptr) && (!(who->flags & FLAGS_TS8) || ((*curr == 'o') &&
1149               !(member->flags & (CHFL_SERVOPOK | CHFL_CHANOP)))))
1150             *badop = ((member->flags & CHFL_DEOPPED) && (*curr == 'o')) ? 2 : 3;
1151           lp->flags = (*curr == 'o') ? MODE_CHANOP : MODE_VOICE;
1152           lp->flags |= MODE_ADD;
1153         }
1154         else if (whatt == MODE_DEL)
1155         {
1156           lp = &chops[opcnt++];
1157           lp->value.cptr = who;
1158           doesdeop = 1;         /* Also when -v */
1159           lp->flags = (*curr == 'o') ? MODE_CHANOP : MODE_VOICE;
1160           lp->flags |= MODE_DEL;
1161         }
1162         if (*curr == 'o')
1163           doesop = 1;
1164         break;
1165       case 'k':
1166         if (--parc <= 0)
1167           break;
1168         parv++;
1169         /* check now so we eat the parameter if present */
1170         if (keychange)
1171           break;
1172         else
1173         {
1174           char *s = &(*parv)[-1];
1175           unsigned short count = KEYLEN + 1;
1176
1177           while (*++s > ' ' && *s != ':' && --count);
1178           *s = '\0';
1179           if (!**parv)          /* nothing left in key */
1180             break;
1181         }
1182         if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1183           break;
1184         if (whatt == MODE_ADD)
1185         {
1186           if (*mode->key && !IsServer(cptr))
1187             sendto_one(cptr, err_str(ERR_KEYSET),
1188                 me.name, cptr->name, chptr->chname);
1189           else if (!*mode->key || IsServer(cptr))
1190           {
1191             lp = &chops[opcnt++];
1192             lp->value.cp = *parv;
1193             if (strlen(lp->value.cp) > (size_t)KEYLEN)
1194               lp->value.cp[KEYLEN] = '\0';
1195             lp->flags = MODE_KEY | MODE_ADD;
1196             keychange = 1;
1197           }
1198         }
1199         else if (whatt == MODE_DEL)
1200         {
1201           if (strCasediff(mode->key, *parv) == 0 || IsServer(cptr))
1202           {
1203             lp = &chops[opcnt++];
1204             lp->value.cp = mode->key;
1205             lp->flags = MODE_KEY | MODE_DEL;
1206             keychange = 1;
1207           }
1208         }
1209         break;
1210       case 'b':
1211         if (--parc <= 0)
1212         {
1213           if (banlsent)         /* Only send it once */
1214             break;
1215           for (lp = chptr->banlist; lp; lp = lp->next)
1216             sendto_one(cptr, rpl_str(RPL_BANLIST), me.name, cptr->name,
1217                 chptr->chname, lp->value.ban.banstr, lp->value.ban.who,
1218                 lp->value.ban.when);
1219           sendto_one(cptr, rpl_str(RPL_ENDOFBANLIST), me.name, cptr->name,
1220               chptr->chname);
1221           banlsent = 1;
1222           break;
1223         }
1224         parv++;
1225         if (BadPtr(*parv))
1226           break;
1227         if (MyUser(sptr))
1228         {
1229           if ((cp = strchr(*parv, ' ')))
1230             *cp = 0;
1231           if (opcnt >= MAXMODEPARAMS || **parv == ':' || **parv == '\0')
1232             break;
1233         }
1234         if (whatt == MODE_ADD)
1235         {
1236           lp = &chops[opcnt++];
1237           lp->value.cp = *parv;
1238           lp->flags = MODE_ADD | MODE_BAN;
1239         }
1240         else if (whatt == MODE_DEL)
1241         {
1242           lp = &chops[opcnt++];
1243           lp->value.cp = *parv;
1244           lp->flags = MODE_DEL | MODE_BAN;
1245         }
1246         break;
1247       case 'l':
1248         /*
1249          * limit 'l' to only *1* change per mode command but
1250          * eat up others.
1251          */
1252         if (limitset)
1253         {
1254           if (whatt == MODE_ADD && --parc > 0)
1255             parv++;
1256           break;
1257         }
1258         if (whatt == MODE_DEL)
1259         {
1260           limitset = 1;
1261           nusers = 0;
1262           break;
1263         }
1264         if (--parc > 0)
1265         {
1266           if (BadPtr(*parv))
1267             break;
1268           if (MyUser(sptr) && opcnt >= MAXMODEPARAMS)
1269             break;
1270           if (!(nusers = atoi(*++parv)))
1271             continue;
1272           lp = &chops[opcnt++];
1273           lp->flags = MODE_ADD | MODE_LIMIT;
1274           limitset = 1;
1275           break;
1276         }
1277         sendto_one(cptr, err_str(ERR_NEEDMOREPARAMS),
1278             me.name, cptr->name, "MODE +l");
1279         break;
1280       case 'i':         /* falls through for default case */
1281         if (whatt == MODE_DEL)
1282           while ((lp = chptr->invites))
1283             del_invite(lp->value.cptr, chptr);
1284       default:
1285         for (ip = flags; *ip; ip += 2)
1286           if (*(ip + 1) == *curr)
1287             break;
1288
1289         if (*ip)
1290         {
1291           if (whatt == MODE_ADD)
1292           {
1293             if (*ip == MODE_PRIVATE)
1294               newmode &= ~MODE_SECRET;
1295             else if (*ip == MODE_SECRET)
1296               newmode &= ~MODE_PRIVATE;
1297             newmode |= *ip;
1298           }
1299           else
1300             newmode &= ~*ip;
1301         }
1302         else if (!IsServer(cptr))
1303           sendto_one(cptr, err_str(ERR_UNKNOWNMODE),
1304               me.name, cptr->name, *curr);
1305         break;
1306     }
1307     curr++;
1308     /*
1309      * Make sure mode strings such as "+m +t +p +i" are parsed
1310      * fully.
1311      */
1312     if (!*curr && parc > 0)
1313     {
1314       curr = *++parv;
1315       parc--;
1316       /* If this was from a server, and it is the last
1317        * parameter and it starts with a digit, it must
1318        * be the creationtime.  --Run
1319        */
1320       if (IsServer(sptr))
1321       {
1322         if (parc == 1 && isDigit(*curr))
1323         {
1324           newtime = atoi(curr);
1325           if (newtime && chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
1326           {
1327             chptr->creationtime = newtime;
1328             *badop = 0;
1329           }
1330           gotts = 1;
1331           if (newtime == 0)
1332           {
1333             *badop = 2;
1334             hacknotice = 1;
1335           }
1336           else if (newtime > chptr->creationtime)
1337           {                     /* It is a net-break ride if we have ops.
1338                                    bounce modes if we have ops.  --Run */
1339             if (doesdeop)
1340               *badop = 2;
1341             else if (chptr->creationtime == 0)
1342             {
1343               if (chptr->creationtime == 0 || doesop)
1344                 chptr->creationtime = newtime;
1345               *badop = 0;
1346             }
1347             /* Bounce: */
1348             else
1349               *badop = 1;
1350           }
1351           /*
1352            * A legal *badop can occur when two
1353            * people join simultaneously a channel,
1354            * Allow for 10 min of lag (and thus hacking
1355            * on channels younger then 10 min) --Run
1356            */
1357           else if (*badop == 0 ||
1358               chptr->creationtime > (TStime() - TS_LAG_TIME))
1359           {
1360             if (newtime < chptr->creationtime)
1361               chptr->creationtime = newtime;
1362             *badop = 0;
1363           }
1364           break;
1365         }
1366       }
1367       else
1368         *badop = 0;
1369     }
1370   }                             /* end of while loop for MODE processing */
1371
1372   /*
1373    * Now reject non chan ops. Accept modes from opers on local channels
1374    * even if they are deopped
1375    */
1376 #ifdef OPER_MODE_LCHAN
1377   if (!IsServer(cptr) && 
1378       (!tmp || !((tmp->flags & CHFL_CHANOP) || 
1379                  IsOperOnLocalChannel(sptr, chptr->chname))))
1380 #else
1381   if (!IsServer(cptr) && (!tmp || !(tmp->flags & CHFL_CHANOP)))
1382 #endif
1383   {
1384     *badop = 0;
1385     return (opcnt || newmode != mode->mode || limitset || keychange) ? 0 : -1;
1386   }
1387
1388   if (doesop && newtime == 0 && IsServer(sptr))
1389     *badop = 2;
1390
1391   if (*badop >= 2 &&
1392       (aconf = find_conf_host(cptr->confs, sptr->name, CONF_UWORLD)))
1393     *badop = 4;
1394
1395 #ifdef OPER_MODE_LCHAN
1396   bounce = (*badop == 1 || *badop == 2 || 
1397             (is_deopped(sptr, chptr) && 
1398              !IsOperOnLocalChannel(sptr, chptr->chname))) ? 1 : 0;
1399 #else
1400   bounce = (*badop == 1 || *badop == 2 || is_deopped(sptr, chptr)) ? 1 : 0;
1401 #endif
1402
1403   whatt = 0;
1404   for (ip = flags; *ip; ip += 2)
1405     if ((*ip & newmode) && !(*ip & oldm.mode))
1406     {
1407       if (bounce)
1408       {
1409         if (bwhatt != MODE_DEL)
1410         {
1411           *bmbuf++ = '-';
1412           bwhatt = MODE_DEL;
1413         }
1414         *bmbuf++ = *(ip + 1);
1415       }
1416       else
1417       {
1418         if (whatt != MODE_ADD)
1419         {
1420           *mbuf++ = '+';
1421           whatt = MODE_ADD;
1422         }
1423         mode->mode |= *ip;
1424         *mbuf++ = *(ip + 1);
1425       }
1426     }
1427
1428   for (ip = flags; *ip; ip += 2)
1429     if ((*ip & oldm.mode) && !(*ip & newmode))
1430     {
1431       if (bounce)
1432       {
1433         if (bwhatt != MODE_ADD)
1434         {
1435           *bmbuf++ = '+';
1436           bwhatt = MODE_ADD;
1437         }
1438         *bmbuf++ = *(ip + 1);
1439       }
1440       else
1441       {
1442         if (whatt != MODE_DEL)
1443         {
1444           *mbuf++ = '-';
1445           whatt = MODE_DEL;
1446         }
1447         mode->mode &= ~*ip;
1448         *mbuf++ = *(ip + 1);
1449       }
1450     }
1451
1452   blen = nblen = 0;
1453   if (limitset && !nusers && mode->limit)
1454   {
1455     if (bounce)
1456     {
1457       if (bwhatt != MODE_ADD)
1458       {
1459         *bmbuf++ = '+';
1460         bwhatt = MODE_ADD;
1461       }
1462       *bmbuf++ = 'l';
1463       sprintf(numeric, "%-15d", mode->limit);
1464       if ((cp = strchr(numeric, ' ')))
1465         *cp = '\0';
1466       strcat(bpbuf, numeric);
1467       blen += strlen(numeric);
1468       strcat(bpbuf, " ");
1469       strcat(nbpbuf, numeric);
1470       nblen += strlen(numeric);
1471       strcat(nbpbuf, " ");
1472     }
1473     else
1474     {
1475       if (whatt != MODE_DEL)
1476       {
1477         *mbuf++ = '-';
1478         whatt = MODE_DEL;
1479       }
1480       mode->mode &= ~MODE_LIMIT;
1481       mode->limit = 0;
1482       *mbuf++ = 'l';
1483     }
1484   }
1485   /*
1486    * Reconstruct "+bkov" chain.
1487    */
1488   if (opcnt)
1489   {
1490     Reg1 int i = 0;
1491     Reg2 char c = 0;
1492     unsigned int prev_whatt = 0;
1493
1494     for (; i < opcnt; i++)
1495     {
1496       lp = &chops[i];
1497       /*
1498        * make sure we have correct mode change sign
1499        */
1500       if (whatt != (lp->flags & (MODE_ADD | MODE_DEL)))
1501       {
1502         if (lp->flags & MODE_ADD)
1503         {
1504           *mbuf++ = '+';
1505           prev_whatt = whatt;
1506           whatt = MODE_ADD;
1507         }
1508         else
1509         {
1510           *mbuf++ = '-';
1511           prev_whatt = whatt;
1512           whatt = MODE_DEL;
1513         }
1514       }
1515       len = strlen(pbuf);
1516       nlen = strlen(npbuf);
1517       /*
1518        * get c as the mode char and tmp as a pointer to
1519        * the parameter for this mode change.
1520        */
1521       switch (lp->flags & MODE_WPARAS)
1522       {
1523         case MODE_CHANOP:
1524           c = 'o';
1525           cp = lp->value.cptr->name;
1526           break;
1527         case MODE_VOICE:
1528           c = 'v';
1529           cp = lp->value.cptr->name;
1530           break;
1531         case MODE_BAN:
1532           /*
1533            * I made this a bit more user-friendly (tm):
1534            * nick = nick!*@*
1535            * nick!user = nick!user@*
1536            * user@host = *!user@host
1537            * host.name = *!*@host.name    --Run
1538            */
1539           c = 'b';
1540           cp = pretty_mask(lp->value.cp);
1541           break;
1542         case MODE_KEY:
1543           c = 'k';
1544           cp = lp->value.cp;
1545           break;
1546         case MODE_LIMIT:
1547           c = 'l';
1548           sprintf(numeric, "%-15d", nusers);
1549           if ((cp = strchr(numeric, ' ')))
1550             *cp = '\0';
1551           cp = numeric;
1552           break;
1553       }
1554
1555       /* What could be added: cp+' '+' '+<TS>+'\0' */
1556       if (len + strlen(cp) + 13 > (size_t)MODEBUFLEN ||
1557           nlen + strlen(cp) + NUMNICKLEN + 12 > (size_t)MODEBUFLEN)
1558         break;
1559
1560       switch (lp->flags & MODE_WPARAS)
1561       {
1562         case MODE_KEY:
1563           if (strlen(cp) > (size_t)KEYLEN)
1564             *(cp + KEYLEN) = '\0';
1565           if ((whatt == MODE_ADD && (*mode->key == '\0' ||
1566               strCasediff(mode->key, cp) != 0)) ||
1567               (whatt == MODE_DEL && (*mode->key != '\0')))
1568           {
1569             if (bounce)
1570             {
1571               if (*mode->key == '\0')
1572               {
1573                 if (bwhatt != MODE_DEL)
1574                 {
1575                   *bmbuf++ = '-';
1576                   bwhatt = MODE_DEL;
1577                 }
1578                 strcat(bpbuf, cp);
1579                 blen += strlen(cp);
1580                 strcat(bpbuf, " ");
1581                 blen++;
1582                 strcat(nbpbuf, cp);
1583                 nblen += strlen(cp);
1584                 strcat(nbpbuf, " ");
1585                 nblen++;
1586               }
1587               else
1588               {
1589                 if (bwhatt != MODE_ADD)
1590                 {
1591                   *bmbuf++ = '+';
1592                   bwhatt = MODE_ADD;
1593                 }
1594                 strcat(bpbuf, mode->key);
1595                 blen += strlen(mode->key);
1596                 strcat(bpbuf, " ");
1597                 blen++;
1598                 strcat(nbpbuf, mode->key);
1599                 nblen += strlen(mode->key);
1600                 strcat(nbpbuf, " ");
1601                 nblen++;
1602               }
1603               *bmbuf++ = c;
1604               mbuf--;
1605               if (*mbuf != '+' && *mbuf != '-')
1606                 mbuf++;
1607               else
1608                 whatt = prev_whatt;
1609             }
1610             else
1611             {
1612               *mbuf++ = c;
1613               strcat(pbuf, cp);
1614               len += strlen(cp);
1615               strcat(pbuf, " ");
1616               len++;
1617               strcat(npbuf, cp);
1618               nlen += strlen(cp);
1619               strcat(npbuf, " ");
1620               nlen++;
1621               if (whatt == MODE_ADD)
1622                 strncpy(mode->key, cp, KEYLEN);
1623               else
1624                 *mode->key = '\0';
1625             }
1626           }
1627           break;
1628         case MODE_LIMIT:
1629           if (nusers && nusers != mode->limit)
1630           {
1631             if (bounce)
1632             {
1633               if (mode->limit == 0)
1634               {
1635                 if (bwhatt != MODE_DEL)
1636                 {
1637                   *bmbuf++ = '-';
1638                   bwhatt = MODE_DEL;
1639                 }
1640               }
1641               else
1642               {
1643                 if (bwhatt != MODE_ADD)
1644                 {
1645                   *bmbuf++ = '+';
1646                   bwhatt = MODE_ADD;
1647                 }
1648                 sprintf(numeric, "%-15d", mode->limit);
1649                 if ((cp = strchr(numeric, ' ')))
1650                   *cp = '\0';
1651                 strcat(bpbuf, numeric);
1652                 blen += strlen(numeric);
1653                 strcat(bpbuf, " ");
1654                 blen++;
1655                 strcat(nbpbuf, numeric);
1656                 nblen += strlen(numeric);
1657                 strcat(nbpbuf, " ");
1658                 nblen++;
1659               }
1660               *bmbuf++ = c;
1661               mbuf--;
1662               if (*mbuf != '+' && *mbuf != '-')
1663                 mbuf++;
1664               else
1665                 whatt = prev_whatt;
1666             }
1667             else
1668             {
1669               *mbuf++ = c;
1670               strcat(pbuf, cp);
1671               len += strlen(cp);
1672               strcat(pbuf, " ");
1673               len++;
1674               strcat(npbuf, cp);
1675               nlen += strlen(cp);
1676               strcat(npbuf, " ");
1677               nlen++;
1678               mode->limit = nusers;
1679             }
1680           }
1681           break;
1682         case MODE_CHANOP:
1683         case MODE_VOICE:
1684           tmp = find_user_link(chptr->members, lp->value.cptr);
1685           if (lp->flags & MODE_ADD)
1686           {
1687             change = (~tmp->flags) & CHFL_OVERLAP & lp->flags;
1688             if (change && bounce)
1689             {
1690               if (lp->flags & MODE_CHANOP)
1691                 tmp->flags |= CHFL_DEOPPED;
1692               if (bwhatt != MODE_DEL)
1693               {
1694                 *bmbuf++ = '-';
1695                 bwhatt = MODE_DEL;
1696               }
1697               *bmbuf++ = c;
1698               strcat(bpbuf, lp->value.cptr->name);
1699               blen += strlen(lp->value.cptr->name);
1700               strcat(bpbuf, " ");
1701               blen++;
1702               sprintf_irc(nbpbuf + nblen, "%s%s ", NumNick(lp->value.cptr));
1703               nblen += strlen(nbpbuf + nblen);
1704               change = 0;
1705             }
1706             else if (change)
1707             {
1708               tmp->flags |= lp->flags & CHFL_OVERLAP;
1709               if (lp->flags & MODE_CHANOP)
1710               {
1711                 tmp->flags &= ~CHFL_DEOPPED;
1712                 if (IsServer(sptr))
1713                   tmp->flags &= ~CHFL_SERVOPOK;
1714               }
1715             }
1716           }
1717           else
1718           {
1719             change = tmp->flags & CHFL_OVERLAP & lp->flags;
1720             if (change && bounce)
1721             {
1722               if (lp->flags & MODE_CHANOP)
1723                 tmp->flags &= ~CHFL_DEOPPED;
1724               if (bwhatt != MODE_ADD)
1725               {
1726                 *bmbuf++ = '+';
1727                 bwhatt = MODE_ADD;
1728               }
1729               *bmbuf++ = c;
1730               strcat(bpbuf, lp->value.cptr->name);
1731               blen += strlen(lp->value.cptr->name);
1732               strcat(bpbuf, " ");
1733               blen++;
1734               sprintf_irc(nbpbuf + nblen, "%s%s ", NumNick(lp->value.cptr));
1735               blen += strlen(bpbuf + blen);
1736               change = 0;
1737             }
1738             else
1739             {
1740               tmp->flags &= ~change;
1741               if ((change & MODE_CHANOP) && IsServer(sptr))
1742                 tmp->flags |= CHFL_DEOPPED;
1743             }
1744           }
1745           if (change || *badop == 2 || *badop == 4)
1746           {
1747             *mbuf++ = c;
1748             strcat(pbuf, cp);
1749             len += strlen(cp);
1750             strcat(pbuf, " ");
1751             len++;
1752             sprintf_irc(npbuf + nlen, "%s%s ", NumNick(lp->value.cptr));
1753             nlen += strlen(npbuf + nlen);
1754             npbuf[nlen++] = ' ';
1755             npbuf[nlen] = 0;
1756           }
1757           else
1758           {
1759             mbuf--;
1760             if (*mbuf != '+' && *mbuf != '-')
1761               mbuf++;
1762             else
1763               whatt = prev_whatt;
1764           }
1765           break;
1766         case MODE_BAN:
1767 /*
1768  * Only bans aren't bounced, it makes no sense to bounce last second
1769  * bans while propagating bans done before the net.rejoin. The reason
1770  * why I don't bounce net.rejoin bans is because it is too much
1771  * work to take care of too long strings adding the necessary TS to
1772  * net.burst bans -- RunLazy
1773  * We do have to check for *badop==2 now, we don't want HACKs to take
1774  * effect.
1775  *
1776  * Since BURST - I *did* implement net.rejoin ban bouncing. So now it
1777  * certainly makes sense to also bounce 'last second' bans (bans done
1778  * after the net.junction). -- RunHardWorker
1779  */
1780           if ((change = (whatt & MODE_ADD) &&
1781               !add_banid(sptr, chptr, cp, !bounce, !add_banid_called)))
1782             add_banid_called = 1;
1783           else
1784             change = (whatt & MODE_DEL) && !del_banid(chptr, cp, !bounce);
1785
1786           if (bounce && change)
1787           {
1788             change = 0;
1789             if ((whatt & MODE_ADD))
1790             {
1791               if (bwhatt != MODE_DEL)
1792               {
1793                 *bmbuf++ = '-';
1794                 bwhatt = MODE_DEL;
1795               }
1796             }
1797             else if ((whatt & MODE_DEL))
1798             {
1799               if (bwhatt != MODE_ADD)
1800               {
1801                 *bmbuf++ = '+';
1802                 bwhatt = MODE_ADD;
1803               }
1804             }
1805             *bmbuf++ = c;
1806             strcat(bpbuf, cp);
1807             blen += strlen(cp);
1808             strcat(bpbuf, " ");
1809             blen++;
1810             strcat(nbpbuf, cp);
1811             nblen += strlen(cp);
1812             strcat(nbpbuf, " ");
1813             nblen++;
1814           }
1815           if (change)
1816           {
1817             *mbuf++ = c;
1818             strcat(pbuf, cp);
1819             len += strlen(cp);
1820             strcat(pbuf, " ");
1821             len++;
1822             strcat(npbuf, cp);
1823             nlen += strlen(cp);
1824             strcat(npbuf, " ");
1825             nlen++;
1826           }
1827           else
1828           {
1829             mbuf--;
1830             if (*mbuf != '+' && *mbuf != '-')
1831               mbuf++;
1832             else
1833               whatt = prev_whatt;
1834           }
1835           break;
1836       }
1837     }                           /* for (; i < opcnt; i++) */
1838   }                             /* if (opcnt) */
1839
1840   *mbuf++ = '\0';
1841   *bmbuf++ = '\0';
1842
1843   /* Bounce here */
1844   if (!hacknotice && *bmodebuf && chptr->creationtime)
1845   {
1846     if (Protocol(cptr) < 10)
1847       sendto_one(cptr, ":%s MODE %s %s %s " TIME_T_FMT,
1848           me.name, chptr->chname, bmodebuf, bparambuf,
1849           *badop == 2 ? (time_t) 0 : chptr->creationtime);
1850     else
1851       sendto_one(cptr, "%s MODE %s %s %s " TIME_T_FMT,
1852           NumServ(&me), chptr->chname, bmodebuf, nbparambuf,
1853           *badop == 2 ? (time_t) 0 : chptr->creationtime);
1854   }
1855   /* If there are possibly bans to re-add, bounce them now */
1856   if (add_banid_called && bounce)
1857   {
1858     Link *ban[6];               /* Max 6 bans at a time */
1859     size_t len[6], sblen, total_len;
1860     int cnt, delayed = 0;
1861     while (delayed || (ban[0] = next_overlapped_ban()))
1862     {
1863       len[0] = strlen(ban[0]->value.ban.banstr);
1864       cnt = 1;                  /* We already got one ban :) */
1865       sblen = sprintf_irc(sendbuf, ":%s MODE %s +b",
1866           me.name, chptr->chname) - sendbuf;
1867       total_len = sblen + 1 + len[0];   /* 1 = ' ' */
1868       /* Find more bans: */
1869       delayed = 0;
1870       while (cnt < 6 && (ban[cnt] = next_overlapped_ban()))
1871       {
1872         len[cnt] = strlen(ban[cnt]->value.ban.banstr);
1873         if (total_len + 5 + len[cnt] > BUFSIZE) /* 5 = "b \r\n\0" */
1874         {
1875           delayed = cnt + 1;    /* != 0 */
1876           break;                /* Flush */
1877         }
1878         sendbuf[sblen++] = 'b';
1879         total_len += 2 + len[cnt++];    /* 2 = "b " */
1880       }
1881       while (cnt--)
1882       {
1883         sendbuf[sblen++] = ' ';
1884         strcpy(sendbuf + sblen, ban[cnt]->value.ban.banstr);
1885         sblen += len[cnt];
1886       }
1887       sendbufto_one(cptr);      /* Send bounce to uplink */
1888       if (delayed)
1889         ban[0] = ban[delayed - 1];
1890     }
1891   }
1892   /* Send -b's of overlapped bans to clients to keep them synchronized */
1893   if (add_banid_called && !bounce)
1894   {
1895     Link *ban;
1896     char *banstr[6];            /* Max 6 bans at a time */
1897     size_t len[6], sblen, psblen, total_len;
1898     int cnt, delayed = 0;
1899     Link *lp;
1900     aClient *acptr;
1901     if (IsServer(sptr))
1902       psblen = sprintf_irc(sendbuf, ":%s MODE %s -b",
1903           sptr->name, chptr->chname) - sendbuf;
1904     else                        /* We rely on IsRegistered(sptr) being true for MODE */
1905       psblen = sprintf_irc(sendbuf, ":%s!%s@%s MODE %s -b", sptr->name,
1906           sptr->user->username, sptr->user->host, chptr->chname) - sendbuf;
1907     while (delayed || (ban = next_removed_overlapped_ban()))
1908     {
1909       if (!delayed)
1910       {
1911         len[0] = strlen((banstr[0] = ban->value.ban.banstr));
1912         ban->value.ban.banstr = NULL;
1913       }
1914       cnt = 1;                  /* We already got one ban :) */
1915       sblen = psblen;
1916       total_len = sblen + 1 + len[0];   /* 1 = ' ' */
1917       /* Find more bans: */
1918       delayed = 0;
1919       while (cnt < 6 && (ban = next_removed_overlapped_ban()))
1920       {
1921         len[cnt] = strlen((banstr[cnt] = ban->value.ban.banstr));
1922         ban->value.ban.banstr = NULL;
1923         if (total_len + 5 + len[cnt] > BUFSIZE) /* 5 = "b \r\n\0" */
1924         {
1925           delayed = cnt + 1;    /* != 0 */
1926           break;                /* Flush */
1927         }
1928         sendbuf[sblen++] = 'b';
1929         total_len += 2 + len[cnt++];    /* 2 = "b " */
1930       }
1931       while (cnt--)
1932       {
1933         sendbuf[sblen++] = ' ';
1934         strcpy(sendbuf + sblen, banstr[cnt]);
1935         RunFree(banstr[cnt]);
1936         sblen += len[cnt];
1937       }
1938       for (lp = chptr->members; lp; lp = lp->next)
1939         if (MyConnect(acptr = lp->value.cptr) && !(lp->flags & CHFL_ZOMBIE))
1940           sendbufto_one(acptr);
1941       if (delayed)
1942       {
1943         banstr[0] = banstr[delayed - 1];
1944         len[0] = len[delayed - 1];
1945       }
1946     }
1947   }
1948
1949   return gotts ? 1 : -1;
1950 }
1951
1952 /* We are now treating the <key> part of /join <channel list> <key> as a key
1953  * ring; that is, we try one key against the actual channel key, and if that
1954  * doesn't work, we try the next one, and so on. -Kev -Texaco
1955  * Returns: 0 on match, 1 otherwise
1956  * This version contributed by SeKs <intru@info.polymtl.ca>
1957  */
1958 static int compall(char *key, char *keyring)
1959 {
1960   register char *p1;
1961
1962 top:
1963   p1 = key;                     /* point to the key... */
1964   while (*p1 && *p1 == *keyring)
1965   {                             /* step through the key and ring until they
1966                                    don't match... */
1967     p1++;
1968     keyring++;
1969   }
1970
1971   if (!*p1 && (!*keyring || *keyring == ','))
1972     /* ok, if we're at the end of the and also at the end of one of the keys
1973        in the keyring, we have a match */
1974     return 0;
1975
1976   if (!*keyring)                /* if we're at the end of the key ring, there
1977                                    weren't any matches, so we return 1 */
1978     return 1;
1979
1980   /* Not at the end of the key ring, so step
1981      through to the next key in the ring: */
1982   while (*keyring && *(keyring++) != ',');
1983
1984   goto top;                     /* and check it against the key */
1985 }
1986
1987 static int can_join(aClient *sptr, aChannel *chptr, char *key)
1988 {
1989   Reg1 Link *lp;
1990   int overrideJoin = 0;  
1991   
1992 #ifdef OPER_WALK_THROUGH_LMODES
1993   /* An oper can force a join on a local channel using "OVERRIDE" as the key. 
1994      a HACK(4) notice will be sent if he would not have been supposed
1995      to join normally. */ 
1996   if (IsOperOnLocalChannel(sptr,chptr->chname) && !BadPtr(key) && 
1997        compall("OVERRIDE",key) == 0)
1998     overrideJoin = MAGIC_OPER_OVERRIDE;
1999 #endif
2000   /*
2001    * Now a banned user CAN join if invited -- Nemesi
2002    * Now a user CAN escape channel limit if invited -- bfriendly
2003    */
2004   if ((chptr->mode.mode & MODE_INVITEONLY) || (is_banned(sptr, chptr, NULL)
2005       || (chptr->mode.limit && chptr->users >= chptr->mode.limit)))
2006   {
2007     for (lp = sptr->user->invited; lp; lp = lp->next)
2008       if (lp->value.chptr == chptr)
2009         break;
2010     if (!lp)
2011     {
2012       if (chptr->mode.limit && chptr->users >= chptr->mode.limit)
2013         return (overrideJoin + ERR_CHANNELISFULL);
2014       /*
2015        * This can return an "Invite only" msg instead of the "You are banned"
2016        * if _both_ conditions are true, but who can say what is more
2017        * appropriate ? checking again IsBanned would be _SO_ cpu-xpensive !
2018        */
2019       return overrideJoin + ((chptr->mode.mode & MODE_INVITEONLY) ?
2020           ERR_INVITEONLYCHAN : ERR_BANNEDFROMCHAN);
2021     }
2022   }
2023
2024   /* now using compall (above) to test against a whole key ring -Kev */
2025   if (*chptr->mode.key && (BadPtr(key) || compall(chptr->mode.key, key)))
2026     return overrideJoin + (ERR_BADCHANNELKEY);
2027
2028   return 0;
2029 }
2030
2031 /*
2032  * Remove bells and commas from channel name
2033  */
2034
2035 static void clean_channelname(char *cn)
2036 {
2037   for (; *cn; cn++)
2038   {
2039     if (!isIrcCh(*cn))
2040     {
2041       *cn = '\0';
2042       return;
2043     }
2044     if (isIrcCl(*cn))
2045 #ifndef FIXME
2046     {
2047 #endif
2048       *cn = toLower(*cn);
2049 #ifndef FIXME
2050       /* Missed the Icelandic letter ETH last time: */
2051       if ((unsigned char)(*cn) == 0xd0)
2052         *cn = (char)0xf0;
2053     }
2054 #endif
2055   }
2056 }
2057
2058 /*
2059  *  Get Channel block for i (and allocate a new channel
2060  *  block, if it didn't exists before).
2061  */
2062 static aChannel *get_channel(aClient *cptr, char *chname, int flag)
2063 {
2064   Reg1 aChannel *chptr;
2065   int len;
2066
2067   if (BadPtr(chname))
2068     return NULL;
2069
2070   len = strlen(chname);
2071   if (MyUser(cptr) && len > CHANNELLEN)
2072   {
2073     len = CHANNELLEN;
2074     *(chname + CHANNELLEN) = '\0';
2075   }
2076   if ((chptr = FindChannel(chname)))
2077     return (chptr);
2078   if (flag == CREATE)
2079   {
2080     chptr = (aChannel *)RunMalloc(sizeof(aChannel) + len);
2081     ++nrof.channels;
2082     memset(chptr, 0, sizeof(aChannel));
2083     strcpy(chptr->chname, chname);
2084     if (channel)
2085       channel->prevch = chptr;
2086     chptr->prevch = NULL;
2087     chptr->nextch = channel;
2088     chptr->creationtime = MyUser(cptr) ? TStime() : (time_t) 0;
2089     channel = chptr;
2090     hAddChannel(chptr);
2091   }
2092   return chptr;
2093 }
2094
2095 static void add_invite(aClient *cptr, aChannel *chptr)
2096 {
2097   Reg1 Link *inv, **tmp;
2098
2099   del_invite(cptr, chptr);
2100   /*
2101    * Delete last link in chain if the list is max length
2102    */
2103   if (list_length(cptr->user->invited) >= MAXCHANNELSPERUSER)
2104     del_invite(cptr, cptr->user->invited->value.chptr);
2105   /*
2106    * Add client to channel invite list
2107    */
2108   inv = make_link();
2109   inv->value.cptr = cptr;
2110   inv->next = chptr->invites;
2111   chptr->invites = inv;
2112   /*
2113    * Add channel to the end of the client invite list
2114    */
2115   for (tmp = &(cptr->user->invited); *tmp; tmp = &((*tmp)->next));
2116   inv = make_link();
2117   inv->value.chptr = chptr;
2118   inv->next = NULL;
2119   (*tmp) = inv;
2120 }
2121
2122 /*
2123  * Delete Invite block from channel invite list and client invite list
2124  */
2125 void del_invite(aClient *cptr, aChannel *chptr)
2126 {
2127   Reg1 Link **inv, *tmp;
2128
2129   for (inv = &(chptr->invites); (tmp = *inv); inv = &tmp->next)
2130     if (tmp->value.cptr == cptr)
2131     {
2132       *inv = tmp->next;
2133       free_link(tmp);
2134       break;
2135     }
2136
2137   for (inv = &(cptr->user->invited); (tmp = *inv); inv = &tmp->next)
2138     if (tmp->value.chptr == chptr)
2139     {
2140       *inv = tmp->next;
2141       free_link(tmp);
2142       break;
2143     }
2144 }
2145
2146 /* List and skip all channels that are listen */
2147 void list_next_channels(aClient *cptr, int nr)
2148 {
2149   aListingArgs *args = cptr->listing;
2150   aChannel *chptr = args->chptr;
2151   chptr->mode.mode &= ~MODE_LISTED;
2152   while (is_listed(chptr) || --nr >= 0)
2153   {
2154     for (; chptr; chptr = chptr->nextch)
2155     {
2156       if (!cptr->user || (SecretChannel(chptr) && !IsMember(cptr, chptr)))
2157         continue;
2158       if (chptr->users > args->min_users && chptr->users < args->max_users &&
2159           chptr->creationtime > args->min_time &&
2160           chptr->creationtime < args->max_time &&
2161           (!args->topic_limits || (*chptr->topic &&
2162           chptr->topic_time > args->min_topic_time &&
2163           chptr->topic_time < args->max_topic_time)))
2164       {
2165         sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name,
2166             ShowChannel(cptr, chptr) ? chptr->chname : "*",
2167             chptr->users, ShowChannel(cptr, chptr) ? chptr->topic : "");
2168         chptr = chptr->nextch;
2169         break;
2170       }
2171     }
2172     if (!chptr)
2173     {
2174       RunFree(cptr->listing);
2175       cptr->listing = NULL;
2176       sendto_one(cptr, rpl_str(RPL_LISTEND), me.name, cptr->name);
2177       break;
2178     }
2179   }
2180   if (chptr)
2181   {
2182     cptr->listing->chptr = chptr;
2183     chptr->mode.mode |= MODE_LISTED;
2184   }
2185 }
2186
2187 /*
2188  *  Subtract one user from channel i (and free channel
2189  *  block, if channel became empty).
2190  */
2191 static void sub1_from_channel(aChannel *chptr)
2192 {
2193   Reg2 Link *tmp;
2194   Link *obtmp;
2195
2196   if (chptr->users > 1)         /* Can be 0, called for an empty channel too */
2197   {
2198     --chptr->users;
2199     return;
2200   }
2201
2202   /* Channel became (or was) empty: Remove channel */
2203   if (is_listed(chptr))
2204   {
2205     int i;
2206     for (i = 0; i <= highest_fd; i++)
2207     {
2208       aClient *acptr;
2209       if ((acptr = loc_clients[i]) && acptr->listing &&
2210           acptr->listing->chptr == chptr)
2211       {
2212         list_next_channels(acptr, 1);
2213         break;                  /* Only one client can list a channel */
2214       }
2215     }
2216   }
2217   /*
2218    * Now, find all invite links from channel structure
2219    */
2220   while ((tmp = chptr->invites))
2221     del_invite(tmp->value.cptr, chptr);
2222
2223   tmp = chptr->banlist;
2224   while (tmp)
2225   {
2226     obtmp = tmp;
2227     tmp = tmp->next;
2228     RunFree(obtmp->value.ban.banstr);
2229     RunFree(obtmp->value.ban.who);
2230     free_link(obtmp);
2231   }
2232   if (chptr->prevch)
2233     chptr->prevch->nextch = chptr->nextch;
2234   else
2235     channel = chptr->nextch;
2236   if (chptr->nextch)
2237     chptr->nextch->prevch = chptr->prevch;
2238   hRemChannel(chptr);
2239   --nrof.channels;
2240   RunFree((char *)chptr);
2241 }
2242
2243 /*
2244  * m_join
2245  *
2246  * parv[0] = sender prefix
2247  * parv[1] = channel
2248  * parv[2] = channel keys (client), or channel TS (server)
2249  */
2250 int m_join(aClient *cptr, aClient *sptr, int parc, char *parv[])
2251 {
2252   static char jbuf[BUFSIZE], mbuf[BUFSIZE];
2253   Reg1 Link *lp;
2254   Reg3 aChannel *chptr;
2255   Reg4 char *name, *keysOrTS = NULL;
2256   int i = 0, zombie = 0, sendcreate = 0;
2257   unsigned int flags = 0;
2258   size_t jlen = 0, mlen = 0;
2259   size_t *buflen;
2260   char *p = NULL, *bufptr;
2261
2262   if (parc < 2 || *parv[1] == '\0')
2263   {
2264     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "JOIN");
2265     return 0;
2266   }
2267
2268   for (p = parv[1]; *p; p++)    /* find the last "JOIN 0" in the line -Kev */
2269     if (*p == '0'
2270         && (*(p + 1) == ',' || *(p + 1) == '\0' || !isIrcCh(*(p + 1))))
2271     {
2272       /* If it's a single "0", remember the place; we will start parsing
2273          the channels after the last 0 in the line -Kev */
2274       parv[1] = p;
2275       if (!*(p + 1))
2276         break;
2277       p++;
2278     }
2279     else
2280     {                           /* Step through to the next comma or until the
2281                                    end of the line, in an attempt to save CPU
2282                                    -Kev */
2283       while (*p != ',' && *p != '\0')
2284         p++;
2285       if (!*p)
2286         break;
2287     }
2288
2289   keysOrTS = parv[2];           /* Remember where our keys are or the TS is;
2290                                    parv[2] needs to be NULL for the call to
2291                                    m_names below -Kev */
2292   parv[2] = p = NULL;
2293
2294   *jbuf = *mbuf = '\0';         /* clear both join and mode buffers -Kev */
2295   /*
2296    *  Rebuild list of channels joined to be the actual result of the
2297    *  JOIN.  Note that "JOIN 0" is the destructive problem.
2298    */
2299   for (name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ","))
2300   {
2301     size_t len;
2302     if (MyConnect(sptr))
2303       clean_channelname(name);
2304     else if (IsLocalChannel(name))
2305       continue;
2306     if (*name == '0' && *(name + 1) == '\0')
2307     {
2308       /* Remove the user from all his channels -Kev */
2309       while ((lp = sptr->user->channel))
2310       {
2311         chptr = lp->value.chptr;
2312         if (!is_zombie(sptr, chptr))
2313           sendto_channel_butserv(chptr, sptr, PartFmt2,
2314               parv[0], chptr->chname, "Left all channels");
2315         remove_user_from_channel(sptr, chptr);
2316       }
2317       /* Just in case */
2318       *mbuf = *jbuf = '\0';
2319       mlen = jlen = 0;
2320     }
2321     else
2322     {                           /* not a /join 0, so treat it as
2323                                    a /join #channel -Kev */
2324       if (!IsChannelName(name))
2325       {
2326         if (MyUser(sptr))
2327           sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
2328         continue;
2329       }
2330
2331       if (MyConnect(sptr))
2332       { 
2333 #ifdef BADCHAN
2334         if(bad_channel(name) && !IsAnOper(sptr))
2335         {
2336           sendto_one(sptr, err_str(ERR_BADCHANNAME), me.name, parv[0],name);
2337           continue;
2338         }
2339 #endif
2340
2341         /*
2342          * Local client is first to enter previously nonexistant
2343          * channel so make them (rightfully) the Channel Operator.
2344          * This looks kind of ugly because we try to avoid calling the strlen()
2345          */
2346         if (ChannelExists(name))
2347         {
2348           flags = CHFL_DEOPPED;
2349           sendcreate = 0;
2350         }
2351         else if (strlen(name) > CHANNELLEN)
2352         {
2353           *(name + CHANNELLEN) = '\0';
2354           if (ChannelExists(name))
2355           {
2356             flags = CHFL_DEOPPED;
2357             sendcreate = 0;
2358           }
2359           else
2360           {
2361             flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
2362             sendcreate = 1;
2363           }
2364         }
2365         else
2366         {
2367           flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
2368           sendcreate = 1;
2369         }
2370
2371 #ifdef OPER_NO_CHAN_LIMIT
2372         /*
2373          * Opers are allowed to join any number of channels
2374          */
2375         if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsAnOper(sptr))
2376 #else
2377         if (sptr->user->joined >= MAXCHANNELSPERUSER)
2378 #endif
2379         {
2380           chptr = get_channel(sptr, name, !CREATE);
2381           sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
2382               me.name, parv[0], chptr ? chptr->chname : name);
2383           break;                /* Can't return, else he won't get on ANY
2384                                    channels!  Break out of the for loop instead.
2385                                    -Kev */
2386         }
2387       }
2388       chptr = get_channel(sptr, name, CREATE);
2389       if (chptr && (lp = find_user_link(chptr->members, sptr)))
2390       {
2391         if (lp->flags & CHFL_ZOMBIE)
2392         {
2393           zombie = 1;
2394           flags = lp->flags & (CHFL_DEOPPED | CHFL_SERVOPOK);
2395           remove_user_from_channel(sptr, chptr);
2396           chptr = get_channel(sptr, name, CREATE);
2397         }
2398         else
2399           continue;
2400       }
2401       name = chptr->chname;
2402       if (!chptr->creationtime) /* A remote JOIN created this channel ? */
2403         chptr->creationtime = MAGIC_REMOTE_JOIN_TS;
2404       if (parc > 2)
2405       {
2406         if (chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
2407           chptr->creationtime = atoi(keysOrTS);
2408         else
2409           parc = 2;             /* Don't pass it on */
2410       }
2411       if (!zombie)
2412       {
2413         if (!MyConnect(sptr))
2414           flags = CHFL_DEOPPED;
2415         if (sptr->flags & FLAGS_TS8)
2416           flags |= CHFL_SERVOPOK;
2417       }
2418       if (MyConnect(sptr))
2419       {
2420         int created = chptr->users == 0;
2421         if (check_target_limit(sptr, chptr, chptr->chname, created))
2422         {
2423           if (created)          /* Did we create the channel? */
2424             sub1_from_channel(chptr);   /* Remove it again! */
2425           continue;
2426         }
2427         if ((i = can_join(sptr, chptr, keysOrTS)))
2428         {
2429 #ifdef OPER_WALK_THROUGH_LMODES
2430           if (i > MAGIC_OPER_OVERRIDE)
2431           {
2432             switch(i - MAGIC_OPER_OVERRIDE)
2433             {
2434               case ERR_CHANNELISFULL: i = 'l'; break;
2435               case ERR_INVITEONLYCHAN: i = 'i'; break;
2436               case ERR_BANNEDFROMCHAN: i = 'b'; break;
2437               case ERR_BADCHANNELKEY: i = 'k'; break;
2438             }
2439             sendto_op_mask(SNO_HACK4,"OPER JOIN: %s JOIN %s (overriding +%c)",sptr->name,chptr->chname,i);
2440           }
2441           else
2442           {
2443             sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
2444             continue; 
2445           }
2446 #else     
2447           sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
2448           continue;
2449 #endif
2450         }
2451       }
2452       /*
2453        * Complete user entry to the new channel (if any)
2454        */
2455       add_user_to_channel(chptr, sptr, flags);
2456
2457       /*
2458        * Notify all other users on the new channel
2459        */
2460       sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
2461
2462       if (MyUser(sptr))
2463       {
2464         del_invite(sptr, chptr);
2465         if (chptr->topic[0] != '\0')
2466         {
2467           sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
2468               parv[0], name, chptr->topic);
2469           sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0], name,
2470               chptr->topic_nick, chptr->topic_time);
2471         }
2472         parv[1] = name;
2473         m_names(cptr, sptr, 2, parv);
2474       }
2475     }
2476
2477     /* Select proper buffer; mbuf for creation, jbuf otherwise */
2478
2479     if (*name == '&')
2480       continue;                 /* Head off local channels at the pass */
2481
2482     bufptr = (sendcreate == 0) ? jbuf : mbuf;
2483     buflen = (sendcreate == 0) ? &jlen : &mlen;
2484     len = strlen(name);
2485     if (*buflen < BUFSIZE - len - 2)
2486     {
2487       if (*bufptr)
2488       {
2489         strcat(bufptr, ",");    /* Add to join buf */
2490         *buflen += 1;
2491       }
2492       strncat(bufptr, name, BUFSIZE - *buflen - 1);
2493       *buflen += len;
2494     }
2495     sendcreate = 0;             /* Reset sendcreate */
2496   }
2497
2498 #ifndef NO_PROTOCOL9
2499   if (*jbuf || *mbuf)           /* Propagate joins to P09 servers */
2500     sendto_lowprot_butone(cptr, 9, (*jbuf && *mbuf) ? ":%s JOIN %s,%s" :
2501         ":%s JOIN %s%s", parv[0], jbuf, mbuf);
2502 #endif
2503
2504   if (*jbuf)                    /* Propgate joins to P10 servers */
2505 #ifdef NO_PROTOCOL9
2506     sendto_serv_butone(cptr,
2507         parc > 2 ? ":%s JOIN %s %s" : ":%s JOIN %s", parv[0], jbuf, keysOrTS);
2508 #else
2509     sendto_highprot_butone(cptr, 10,
2510         parc > 2 ? ":%s JOIN %s %s" : ":%s JOIN %s", parv[0], jbuf, keysOrTS);
2511 #endif
2512   if (*mbuf)                    /* and now creation events */
2513 #ifdef NO_PROTOCOL9
2514     sendto_serv_butone(cptr, "%s%s CREATE %s " TIME_T_FMT,
2515         NumNick(sptr), mbuf, TStime());
2516 #else
2517     sendto_highprot_butone(cptr, 10, "%s%s CREATE %s " TIME_T_FMT,
2518         NumNick(sptr), mbuf, TStime());
2519 #endif
2520
2521   if (MyUser(sptr))
2522   {                             /* shouldn't ever set TS for remote JOIN's */
2523     if (*jbuf)
2524     {                           /* check for channels that need TS's */
2525       p = NULL;
2526       for (name = strtoken(&p, jbuf, ","); name; name = strtoken(&p, NULL, ","))
2527       {
2528         chptr = get_channel(sptr, name, !CREATE);
2529         if (chptr && chptr->mode.mode & MODE_SENDTS)
2530         {                       /* send a TS? */
2531           sendto_serv_butone(cptr, ":%s MODE %s + " TIME_T_FMT, me.name,
2532               chptr->chname, chptr->creationtime);      /* ok, send TS */
2533           chptr->mode.mode &= ~MODE_SENDTS;     /* reset flag */
2534         }
2535       }
2536     }
2537
2538     if (*mbuf)
2539     {                           /* ok, send along modes for creation events to P9 */
2540       p = NULL;
2541       for (name = strtoken(&p, mbuf, ","); name; name = strtoken(&p, NULL, ","))
2542       {
2543         chptr = get_channel(sptr, name, !CREATE);
2544         sendto_lowprot_butone(cptr, 9, ":%s MODE %s +o %s " TIME_T_FMT,
2545             me.name, chptr->chname, parv[0], chptr->creationtime);
2546       }
2547     }
2548   }
2549   return 0;
2550 }
2551
2552 /*
2553  * m_destruct
2554  *
2555  * parv[0] = sender prefix
2556  * parv[1] = channel channelname
2557  * parv[2] = channel time stamp
2558  *
2559  * This function does nothing, it does passes DESTRUCT to the other servers.
2560  * In the future we will start to use this message.
2561  *
2562  */
2563 int m_destruct(aClient *cptr, aClient *sptr, int parc, char *parv[])
2564 {
2565   time_t chanTS;                /* Creation time of the channel */
2566
2567   if (parc < 3 || *parv[2] == '\0')
2568     return 0;
2569
2570 #ifdef GODMODE
2571   /* Allow DESTRUCT from user */
2572   if (MyUser(sptr))
2573     sptr = &me;
2574   else
2575 #endif
2576
2577     /* sanity checks: Only accept DESTRUCT messages from servers */
2578   if (!IsServer(sptr))
2579     return 0;
2580
2581   /* Don't pass on DESTRUCT messages for channels that exist */
2582   if (FindChannel(parv[1]))
2583     return 0;
2584
2585   chanTS = atoi(parv[2]);
2586
2587   /* Pass on DESTRUCT message */
2588   sendto_highprot_butone(cptr, 10, "%s DESTRUCT %s " TIME_T_FMT,
2589       NumServ(sptr), parv[1], chanTS);
2590
2591   return 0;
2592 }
2593
2594 /*
2595  * m_create
2596  *
2597  * parv[0] = sender prefix
2598  * parv[1] = channel names
2599  * parv[2] = channel time stamp
2600  */
2601 int m_create(aClient *cptr, aClient *sptr, int parc, char *parv[])
2602 {
2603   char cbuf[BUFSIZE];           /* Buffer for list with channels
2604                                    that `sptr' really creates */
2605   time_t chanTS;                /* Creation time for all channels
2606                                    in the comma seperated list */
2607   char *p, *name;
2608   Reg5 aChannel *chptr;
2609   int badop;
2610
2611   /* sanity checks: Only accept CREATE messages from servers */
2612   if (!IsServer(cptr) || parc < 3 || *parv[2] == '\0')
2613     return 0;
2614
2615   chanTS = atoi(parv[2]);
2616
2617   *cbuf = '\0';                 /* Start with empty buffer */
2618
2619   /* For each channel in the comma seperated list: */
2620   for (name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ","))
2621   {
2622     badop = 0;                  /* Default is to accept the op */
2623     if ((chptr = FindChannel(name)))
2624     {
2625       name = chptr->chname;
2626       if (TStime() - chanTS > TS_LAG_TIME)
2627       {
2628         /* A bounce would not be accepted anyway - if we get here something
2629            is wrong with the TS clock syncing (or we have more then
2630            TS_LAG_TIME lag, or an admin is hacking */
2631         badop = 2;
2632         /* This causes a HACK notice on all upstream servers: */
2633         if (Protocol(cptr) < 10)
2634           sendto_one(cptr, ":%s MODE %s -o %s 0", me.name, name, sptr->name);
2635         else
2636           sendto_one(cptr, ":%s MODE %s -o %s%s 0",
2637               me.name, name, NumNick(sptr));
2638         /* This causes a WALLOPS on all downstream servers and a notice to our
2639            own opers: */
2640         parv[1] = name;         /* Corrupt parv[1], it is not used anymore anyway */
2641         send_hack_notice(cptr, sptr, parc, parv, badop, 2);
2642       }
2643       else if (chptr->creationtime && chanTS > chptr->creationtime &&
2644           chptr->creationtime != MAGIC_REMOTE_JOIN_TS)
2645       {
2646         /* We (try) to bounce the mode, because the CREATE is used on an older
2647            channel, probably a net.ride */
2648         badop = 1;
2649         /* Send a deop upstream: */
2650         if (Protocol(cptr) < 10)
2651           sendto_one(cptr, ":%s MODE %s -o %s " TIME_T_FMT, me.name,
2652               name, sptr->name, chptr->creationtime);
2653         else
2654           sendto_one(cptr, ":%s MODE %s -o %s%s " TIME_T_FMT, me.name,
2655               name, NumNick(sptr), chptr->creationtime);
2656       }
2657     }
2658     else                        /* Channel doesn't exist: create it */
2659       chptr = get_channel(sptr, name, CREATE);
2660
2661     /* Add and mark ops */
2662     add_user_to_channel(chptr, sptr,
2663         (badop || IsModelessChannel(name)) ? CHFL_DEOPPED : CHFL_CHANOP);
2664
2665     /* Send user join to the local clients (if any) */
2666     sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
2667
2668     if (badop)                  /* handle badop: convert CREATE into JOIN */
2669       sendto_serv_butone(cptr, ":%s JOIN %s " TIME_T_FMT,
2670           sptr->name, name, chptr->creationtime);
2671     else
2672     {
2673       /* Send the op to local clients:
2674          (if any; extremely unlikely, but it CAN happen) */
2675       if (!IsModelessChannel(name))
2676         sendto_channel_butserv(chptr, sptr, ":%s MODE %s +o %s",
2677             sptr->user->server->name, name, parv[0]);
2678
2679       /* Set/correct TS and add the channel to the
2680          buffer for accepted channels: */
2681       chptr->creationtime = chanTS;
2682       if (*cbuf)
2683         strcat(cbuf, ",");
2684       strcat(cbuf, name);
2685     }
2686   }
2687
2688   if (*cbuf)                    /* Any channel accepted with ops ? */
2689   {
2690 #ifdef NO_PROTOCOL9
2691     sendto_serv_butone(cptr, "%s%s CREATE %s " TIME_T_FMT,
2692         NumNick(sptr), cbuf, chanTS);
2693 #else
2694     /* send CREATEs to 2.10 servers */
2695     sendto_highprot_butone(cptr, 10, "%s%s CREATE %s " TIME_T_FMT,
2696         NumNick(sptr), cbuf, chanTS);
2697
2698     /* And JOIN + MODE to 2.9 servers; following
2699        is not needed after all are 2.10 */
2700     sendto_lowprot_butone(cptr, 9, ":%s JOIN %s", parv[0], cbuf);
2701     p = NULL;
2702     for (name = strtoken(&p, cbuf, ","); name; name = strtoken(&p, NULL, ","))
2703       sendto_lowprot_butone(cptr, 9, ":%s MODE %s +o %s " TIME_T_FMT,
2704           sptr->user->server->name, name, parv[0], chanTS);
2705 #endif
2706   }
2707
2708   return 0;
2709 }
2710
2711 static size_t prefix_len;
2712
2713 static void add_token_to_sendbuf(char *token, size_t *sblenp, int *firstp,
2714     int *send_itp, char is_a_ban, int mode)
2715 {
2716   int first = *firstp;
2717
2718   /*
2719    * Heh - we do not need to test if it still fits in the buffer, because
2720    * this BURST message is reconstructed from another BURST message, and
2721    * it only can become smaller. --Run
2722    */
2723
2724   if (*firstp)                  /* First token in this parameter ? */
2725   {
2726     *firstp = 0;
2727     if (*send_itp == 0)
2728       *send_itp = 1;            /* Buffer contains data to be sent */
2729     sendbuf[(*sblenp)++] = ' ';
2730     if (is_a_ban)
2731     {
2732       sendbuf[(*sblenp)++] = ':';       /* Bans are always the last "parv" */
2733       sendbuf[(*sblenp)++] = is_a_ban;
2734     }
2735   }
2736   else                          /* Of course, 'send_it' is already set here */
2737     /* Seperate banmasks with a space because
2738        they can contain commas themselfs: */
2739     sendbuf[(*sblenp)++] = is_a_ban ? ' ' : ',';
2740   strcpy(sendbuf + *sblenp, token);
2741   *sblenp += strlen(token);
2742   if (!is_a_ban)                /* nick list ? Need to take care
2743                                    of modes for nicks: */
2744   {
2745     static int last_mode = 0;
2746     mode &= CHFL_CHANOP | CHFL_VOICE;
2747     if (first)
2748       last_mode = 0;
2749     if (last_mode != mode)      /* Append mode like ':ov' if changed */
2750     {
2751       last_mode = mode;
2752       sendbuf[(*sblenp)++] = ':';
2753       if (mode & CHFL_CHANOP)
2754         sendbuf[(*sblenp)++] = 'o';
2755       if (mode & CHFL_VOICE)
2756         sendbuf[(*sblenp)++] = 'v';
2757     }
2758     sendbuf[*sblenp] = '\0';
2759   }
2760 }
2761
2762 static void cancel_mode(aClient *sptr, aChannel *chptr, char m,
2763     const char *param, int *count)
2764 {
2765   static char *pb, *sbp, *sbpi;
2766   int paramdoesntfit = 0;
2767   if (*count == -1)             /* initialize ? */
2768   {
2769     sbp = sbpi =
2770         sprintf_irc(sendbuf, ":%s MODE %s -", sptr->name, chptr->chname);
2771     pb = parabuf;
2772     *count = 0;
2773   }
2774   /* m == 0 means flush */
2775   if (m)
2776   {
2777     if (param)
2778     {
2779       size_t nplen = strlen(param);
2780       if (pb - parabuf + nplen + 23 > MODEBUFLEN)
2781         paramdoesntfit = 1;
2782       else
2783       {
2784         *sbp++ = m;
2785         *pb++ = ' ';
2786         strcpy(pb, param);
2787         pb += nplen;
2788         ++*count;
2789       }
2790     }
2791     else
2792       *sbp++ = m;
2793   }
2794   else if (*count == 0)
2795     return;
2796   if (*count == 6 || !m || paramdoesntfit)
2797   {
2798 #ifndef NO_PROTOCOL9
2799     Dlink *lp;
2800     char *sbe;
2801 #endif
2802     Link *member;
2803     strcpy(sbp, parabuf);
2804 #ifndef NO_PROTOCOL9
2805     sbe = sbp + strlen(parabuf);
2806 #endif
2807     for (member = chptr->members; member; member = member->next)
2808       if (MyUser(member->value.cptr))
2809         sendbufto_one(member->value.cptr);
2810 #ifndef NO_PROTOCOL9
2811     sprintf_irc(sbe, " " TIME_T_FMT, chptr->creationtime);
2812     /* Send 'sendbuf' to all 2.9 downlinks: */
2813     for (lp = me.serv->down; lp; lp = lp->next)
2814       if (Protocol(lp->value.cptr) < 10)
2815         sendbufto_one(lp->value.cptr);
2816 #endif
2817     sbp = sbpi;
2818     pb = parabuf;
2819     *count = 0;
2820   }
2821   if (paramdoesntfit)
2822   {
2823     *sbp++ = m;
2824     *pb++ = ' ';
2825     strcpy(pb, param);
2826     pb += strlen(param);
2827     ++*count;
2828   }
2829 }
2830
2831 /*
2832  * m_burst  --  by Run carlo@runaway.xs4all.nl  december 1995 till march 1997
2833  *
2834  * parv[0] = sender prefix
2835  * parv[1] = channel name
2836  * parv[2] = channel timestamp
2837  * The meaning of the following parv[]'s depend on their first character:
2838  * If parv[n] starts with a '+':
2839  * Net burst, additive modes
2840  *   parv[n] = <mode>
2841  *   parv[n+1] = <param> (optional)
2842  *   parv[n+2] = <param> (optional)
2843  * If parv[n] starts with a '%', then n will be parc-1:
2844  *   parv[n] = %<ban> <ban> <ban> ...
2845  * If parv[n] starts with another character:
2846  *   parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
2847  *   where <mode> is the channel mode (ov) of nick and all following nicks.
2848  *
2849  * Example:
2850  * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
2851  *
2852  * Anti net.ride code.
2853  *
2854  * When the channel already exist, and its TS is larger then
2855  * the TS in the BURST message, then we cancel all existing modes.
2856  * If its is smaller then the received BURST message is ignored.
2857  * If it's equal, then the received modes are just added.
2858  */
2859 int m_burst(aClient *cptr, aClient *sptr, int parc, char *parv[])
2860 {
2861   Reg1 aChannel *chptr;
2862   time_t timestamp;
2863   int netride = 0, wipeout = 0, n;
2864   int send_it = 0, add_banid_not_called = 1;
2865   Mode *current_mode;
2866   size_t sblen, mblen = 0;
2867   int mblen2, pblen2, cnt;
2868   int prev_mode;
2869   char prev_key[KEYLEN + 1];
2870   Link *lp;
2871 #ifndef NO_PROTOCOL9
2872   int ts_sent = 0;
2873 #endif
2874
2875   /* BURST is only for servers and has at least 4 parameters */
2876   if (!IsServer(cptr) || parc < 4)
2877     return 0;
2878
2879   if (!IsBurst(sptr))
2880   {
2881     int i;
2882     char *p;
2883     if (find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))
2884     {
2885       p =
2886           sprintf_irc(sendbuf,
2887           ":%s NOTICE * :*** Notice -- HACK(4): %s BURST %s %s", me.name,
2888           sptr->name, parv[1], parv[2]);
2889       for (i = 3; i < parc - 1; ++i)
2890         p = sprintf_irc(p, " %s", parv[i]);
2891       sprintf_irc(p, " :%s", parv[parc - 1]);
2892       sendbufto_op_mask(SNO_HACK4);
2893     }
2894     else
2895     {
2896 #if 1                           /* FIXME: This should be removed after all HUBs upgraded to ircu2.10.05 */
2897       SetBurst(sptr);
2898       if (MyConnect(sptr))
2899 #endif
2900         return exit_client_msg(cptr, cptr, &me,
2901             "HACK: BURST message outside net.burst from %s", sptr->name);
2902     }
2903   }
2904
2905   /* Find the channel, or create it - note that the creation time
2906    * will be 0 if it has to be created */
2907   chptr = get_channel(sptr, parv[1], CREATE);
2908   current_mode = &chptr->mode;
2909   prev_mode = chptr->mode.mode;
2910   if (*chptr->mode.key)
2911   {
2912     prev_mode |= MODE_KEY;
2913     strcpy(prev_key, chptr->mode.key);
2914   }
2915   if (chptr->mode.limit)
2916     prev_mode |= MODE_LIMIT;
2917
2918   timestamp = atoi(parv[2]);
2919
2920   /* Copy the new TS when the received creationtime appears to be older */
2921   if (!chptr->creationtime || chptr->creationtime > timestamp)
2922   {
2923     /* Set the new timestamp */
2924     chptr->creationtime = timestamp;
2925     send_it = 1;                /* Make sure we pass on the different timestamp ! */
2926     /* Mark all bans as needed to be wiped out */
2927     for (lp = chptr->banlist; lp; lp = lp->next)
2928       lp->flags |= CHFL_BURST_BAN_WIPEOUT;
2929     /*
2930      * Only the first BURST for this channel can have creationtime > timestamp,
2931      * so at this moment ALL members are on OUR side, and thus all net.riders:
2932      */
2933     wipeout = 1;
2934   }
2935   for (lp = chptr->members; lp; lp = lp->next)
2936     lp->flags &= ~CHFL_BURST_JOINED;    /* Set later for nicks in the BURST msg */
2937   /* If `wipeout' is set then these will be deopped later. */
2938
2939   /* If the entering creationtime is younger, ignore the modes */
2940   if (chptr->creationtime < timestamp)
2941     netride = 1;                /* Only pass on the nicks (so they JOIN) */
2942
2943   /* Prepare buffers to pass the message */
2944   *bparambuf = *bmodebuf = *parabuf = '\0';
2945   pblen2 = 0;
2946   *modebuf = '+';
2947   mblen2 = 1;
2948   cnt = 0;
2949   prefix_len = sblen = sprintf_irc(sendbuf, "%s BURST %s " TIME_T_FMT,
2950       NumServ(sptr), chptr->chname, chptr->creationtime) - sendbuf;
2951
2952   /* Run over all remaining parameters */
2953   for (n = 3; n < parc; n++)
2954     switch (*parv[n])           /* What type is it ? mode, nicks or bans ? */
2955     {
2956       case '+':         /* modes */
2957       {
2958         char *p = parv[n];
2959         while (*(++p))          /* Run over all mode characters */
2960         {
2961           switch (*p)           /* which mode ? */
2962           {
2963               /*
2964                * The following cases all do the following:
2965                * - In case wipeout needed, reset 'prev_mode' to indicate this
2966                *   mode should not be cancelled.
2967                * - If wipeout or (not netride and the new mode is a change),
2968                *   add it to bmodebuf and bparabuf for propagation.
2969                * - Else ignore it.
2970                * - Add it to modebuf and parabuf for propagation to the
2971                *   clients when not netride and the new mode is a change.
2972                * Special cases:
2973                * - If a +s is received, cancel a +p and sent a -p to the
2974                *   clients too (if +p was set).
2975                * - If a +p is received and +s is set, ignore the +p.
2976                */
2977             case 'i':
2978             {
2979               register int tmp;
2980               prev_mode &= ~MODE_INVITEONLY;
2981               if (!(tmp = netride ||
2982                   (current_mode->mode & MODE_INVITEONLY)) || wipeout)
2983               {
2984                 bmodebuf[mblen++] = 'i';
2985                 current_mode->mode |= MODE_INVITEONLY;
2986               }
2987               if (!tmp)
2988                 modebuf[mblen2++] = 'i';
2989               break;
2990             }
2991             case 'k':
2992             {
2993               register int tmp;
2994               char *param = parv[++n];
2995               prev_mode &= ~MODE_KEY;
2996               if (!(tmp = netride || (*current_mode->key &&
2997                   (!strcmp(current_mode->key, param) ||
2998                   (!wipeout && strcmp(current_mode->key, param) < 0)))) ||
2999                   wipeout)
3000               {
3001                 bmodebuf[mblen++] = 'k';
3002                 strcat(bparambuf, " ");
3003                 strcat(bparambuf, param);
3004                 strncpy(current_mode->key, param, KEYLEN);
3005               }
3006               if (!tmp && !wipeout)
3007               {
3008                 modebuf[mblen2++] = 'k';
3009                 parabuf[pblen2++] = ' ';
3010                 strcpy(parabuf + pblen2, param);
3011                 pblen2 += strlen(param);
3012                 cnt++;
3013               }
3014               break;
3015             }
3016             case 'l':
3017             {
3018               register int tmp;
3019               unsigned int param = atoi(parv[++n]);
3020               prev_mode &= ~MODE_LIMIT;
3021               if (!(tmp = netride || (current_mode->limit &&
3022                   (current_mode->limit == param ||
3023                   (!wipeout && current_mode->limit < param)))) || wipeout)
3024               {
3025                 bmodebuf[mblen++] = 'l';
3026                 sprintf_irc(bparambuf + strlen(bparambuf), " %d", param);
3027                 current_mode->limit = param;
3028               }
3029               if (!tmp)
3030               {
3031                 modebuf[mblen2++] = 'l';
3032                 pblen2 = sprintf_irc(parabuf + pblen2, " %d", param) - parabuf;
3033                 cnt++;
3034               }
3035               break;
3036             }
3037             case 'm':
3038             {
3039               register int tmp;
3040               prev_mode &= ~MODE_MODERATED;
3041               if (!(tmp = netride ||
3042                   (current_mode->mode & MODE_MODERATED)) || wipeout)
3043               {
3044                 bmodebuf[mblen++] = 'm';
3045                 current_mode->mode |= MODE_MODERATED;
3046               }
3047               if (!tmp)
3048                 modebuf[mblen2++] = 'm';
3049               break;
3050             }
3051             case 'n':
3052             {
3053               register int tmp;
3054               prev_mode &= ~MODE_NOPRIVMSGS;
3055               if (!(tmp = netride ||
3056                   (current_mode->mode & MODE_NOPRIVMSGS)) || wipeout)
3057               {
3058                 bmodebuf[mblen++] = 'n';
3059                 current_mode->mode |= MODE_NOPRIVMSGS;
3060               }
3061               if (!tmp)
3062                 modebuf[mblen2++] = 'n';
3063               break;
3064             }
3065             case 'p':
3066             {
3067               register int tmp;
3068
3069               /* Special case: */
3070               if (!netride && !wipeout && (current_mode->mode & MODE_SECRET))
3071                 break;
3072
3073               prev_mode &= ~MODE_PRIVATE;
3074               if (!(tmp = netride ||
3075                   (current_mode->mode & MODE_PRIVATE)) || wipeout)
3076               {
3077                 bmodebuf[mblen++] = 'p';
3078                 current_mode->mode |= MODE_PRIVATE;
3079               }
3080               if (!tmp)
3081                 modebuf[mblen2++] = 'p';
3082               break;
3083             }
3084             case 's':
3085             {
3086               register int tmp;
3087               prev_mode &= ~MODE_SECRET;
3088               if (!(tmp = netride ||
3089                   (current_mode->mode & MODE_SECRET)) || wipeout)
3090               {
3091                 bmodebuf[mblen++] = 's';
3092                 current_mode->mode |= MODE_SECRET;
3093               }
3094               if (!tmp)
3095                 modebuf[mblen2++] = 's';
3096
3097               /* Special case: */
3098               if (!netride && !wipeout && (current_mode->mode & MODE_PRIVATE))
3099               {
3100                 int i;
3101                 for (i = mblen2 - 1; i >= 0; --i)
3102                   modebuf[i + 2] = modebuf[i];
3103                 modebuf[0] = '-';
3104                 modebuf[1] = 'p';
3105                 mblen2 += 2;
3106                 current_mode->mode &= ~MODE_PRIVATE;
3107               }
3108
3109               break;
3110             }
3111             case 't':
3112             {
3113               register int tmp;
3114               prev_mode &= ~MODE_TOPICLIMIT;
3115               if (!(tmp = netride ||
3116                   (current_mode->mode & MODE_TOPICLIMIT)) || wipeout)
3117               {
3118                 bmodebuf[mblen++] = 't';
3119                 current_mode->mode |= MODE_TOPICLIMIT;
3120               }
3121               if (!tmp)
3122                 modebuf[mblen2++] = 't';
3123               break;
3124             }
3125           }
3126         }                       /* <-- while over all modes */
3127
3128         bmodebuf[mblen] = '\0';
3129         sendbuf[sblen] = '\0';
3130         if (mblen)              /* Anything to send at all ? */
3131         {
3132           send_it = 1;
3133           strcpy(sendbuf + sblen, " +");
3134           sblen += 2;
3135           strcpy(sendbuf + sblen, bmodebuf);
3136           sblen += mblen;
3137           strcpy(sendbuf + sblen, bparambuf);
3138           sblen += strlen(bparambuf);
3139         }
3140         break;                  /* Done mode part */
3141       }
3142       case '%':         /* bans */
3143       {
3144         char *pv, *p = NULL, *ban;
3145         int first = 1;
3146         if (netride)
3147           break;                /* Ignore bans */
3148         /* Run over all bans */
3149         for (pv = parv[n] + 1; (ban = strtoken(&p, pv, " ")); pv = NULL)
3150         {
3151           int ret;
3152           /*
3153            * The following part should do the following:
3154            * - If the new (un)ban is not a _change_ it is ignored.
3155            * - Else, add it to sendbuf for later use.
3156            * - If sendbuf is full, send it, and prepare a new
3157            *   message in sendbuf.
3158            */
3159           ret = add_banid(sptr, chptr, ban, 1, add_banid_not_called);
3160           if (ret == 0)
3161           {
3162             add_banid_not_called = 0;
3163             /* Mark this new ban so we can send it to the clients later */
3164             chptr->banlist->flags |= CHFL_BURST_BAN;
3165           }
3166           if (ret != -1)
3167             /* A new ban was added or an existing one needs to be passed on.
3168              * Also add it to sendbuf: */
3169             add_token_to_sendbuf(ban, &sblen, &first, &send_it, '%', 0);
3170         }
3171         break;                  /* Done bans part */
3172       }
3173       default:                  /* nicks */
3174       {
3175         char *pv, *p = NULL, *nick, *ptr;
3176         int first = 1;
3177         /* Default mode: */
3178         int default_mode = CHFL_DEOPPED;
3179         /* Run over all nicks */
3180         for (pv = parv[n]; (nick = strtoken(&p, pv, ",")); pv = NULL)
3181         {
3182           aClient *acptr;
3183           if ((ptr = strchr(nick, ':')))        /* New default mode ? */
3184           {
3185             *ptr = '\0';        /* Fix 'nick' */
3186             acptr = findNUser(nick);
3187             if (!netride)
3188             {
3189               /* Calculate new mode change: */
3190               default_mode = CHFL_DEOPPED;
3191               while (*(++ptr))
3192                 if (*ptr == 'o')
3193                 {
3194                   default_mode |= CHFL_CHANOP;
3195                   default_mode &= ~CHFL_DEOPPED;
3196                 }
3197                 else if (*ptr == 'v')
3198                   default_mode |= CHFL_VOICE;
3199                 else
3200                   break;
3201             }
3202           }
3203           else
3204             acptr = findNUser(nick);
3205           /*
3206            * Note that at this point we already received a 'NICK' for any
3207            * <nick> numeric that is joining (and possibly opped) here.
3208            * Therefore we consider the following situations:
3209            * - The <nick> numeric exists and is from the direction of cptr: ok
3210            * - The <nick> numeric does not exist:
3211            *   Apparently this previous <nick> numeric was killed (upstream)
3212            *   or it collided with an existing <nick> name.
3213            * - The <nick> numeric exists but is from another direction:
3214            *   Apparently this previous <nick> numeric was killed,
3215            *   and due to a reroute it signed on via another link (probably
3216            *   a nick [numeric] collision).
3217            * Note that it can't be a QUIT or SQUIT, because a QUIT would
3218            * come from the same direction as the BURST (cptr) while an
3219            * upstream SQUIT removes the source (server) and we would thus
3220            * have this BURST ignored already.
3221            * This means that if we find the nick and it is from the correct
3222            * direction, it joins. If it doesn't exist or is from another
3223            * direction, we have to ignore it. If all nicks are ignored, we
3224            * remove the channel again when it is empty and don't propagate
3225            * the BURST message.
3226            */
3227           if (acptr && acptr->from == cptr)
3228           {
3229             /*
3230              * The following should do the following:
3231              * - Add it to sendbuf for later use.
3232              * - If sendbuf is full, send it, and prepare a new
3233              *   message in sendbuf.
3234              */
3235             add_token_to_sendbuf(nick, &sblen, &first, &send_it, 0,
3236                 default_mode);
3237             /* Let is take effect: (Note that in the case of a netride
3238              * 'default_mode' is always CHFL_DEOPPED here). */
3239             add_user_to_channel(chptr, acptr, default_mode);
3240             chptr->members->flags |= CHFL_BURST_JOINED;
3241           }
3242         }                       /* <-- Next nick */
3243         if (!chptr->members)    /* All nicks collided and channel is empty ? */
3244         {
3245           sub1_from_channel(chptr);
3246           return 0;             /* Forget about the (rest of the) message... */
3247         }
3248         break;                  /* Done nicks part */
3249       }
3250     }                           /* <-- Next parameter if any */
3251   if (!chptr->members)          /* This message only contained bans (then the previous
3252                                    message only contained collided nicks, see above) */
3253   {
3254     sub1_from_channel(chptr);
3255     if (!add_banid_not_called)
3256       while (next_removed_overlapped_ban());
3257     return 0;                   /* Forget about the (rest of the) message... */
3258   }
3259
3260   /* The last (possibly only) message is always send here */
3261   if (send_it)                  /* Anything (left) to send ? */
3262   {
3263     Dlink *lp;
3264     Link *member;
3265
3266     /* send 'sendbuf' to all downlinks */
3267     for (lp = me.serv->down; lp; lp = lp->next)
3268     {
3269       if (lp->value.cptr == cptr)
3270         continue;
3271       if (Protocol(lp->value.cptr) > 9)
3272         sendbufto_one(lp->value.cptr);
3273     }
3274
3275     /*
3276      * Now we finally can screw sendbuf again...
3277      * Send all changes to the local clients:
3278      *
3279      * First send all joins and op them, because 2.9 servers
3280      * would protest with a HACK if we first de-opped people.
3281      * However, we don't send the +b bans yes, because we
3282      * DO first want to -b the old bans (otherwise it's confusing).
3283      */
3284
3285     /* Send all joins: */
3286     for (member = chptr->members; member; member = member->next)
3287       if (member->flags & CHFL_BURST_JOINED)
3288       {
3289         sendto_channel_butserv(chptr, member->value.cptr, ":%s JOIN :%s",
3290             member->value.cptr->name, chptr->chname);
3291 #ifndef NO_PROTOCOL9
3292         /* And to 2.9 servers: */
3293         sendto_lowprot_butone(cptr, 9, ":%s JOIN %s",
3294             member->value.cptr->name, chptr->chname);
3295 #endif
3296       }
3297
3298     if (!netride)
3299     {
3300       /* Send all +o and +v modes: */
3301       for (member = chptr->members; member; member = member->next)
3302       {
3303         if ((member->flags & CHFL_BURST_JOINED))
3304         {
3305           int mode = CHFL_CHANOP;
3306           for (;;)
3307           {
3308             if ((member->flags & mode))
3309             {
3310               modebuf[mblen2++] = (mode == CHFL_CHANOP) ? 'o' : 'v';
3311               parabuf[pblen2++] = ' ';
3312               strcpy(parabuf + pblen2, member->value.cptr->name);
3313               pblen2 += strlen(member->value.cptr->name);
3314               if (6 == ++cnt)
3315               {
3316                 modebuf[mblen2] = 0;
3317                 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3318                     parv[0], chptr->chname, modebuf, parabuf);
3319 #ifndef NO_PROTOCOL9
3320                 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3321                     parv[0], chptr->chname, modebuf, parabuf,
3322                     chptr->creationtime);
3323                 ts_sent = 1;
3324 #endif
3325                 *parabuf = 0;
3326                 pblen2 = 0;
3327                 mblen2 = 1;
3328                 cnt = 0;
3329               }
3330             }
3331             if (mode == CHFL_CHANOP)
3332               mode = CHFL_VOICE;
3333             else
3334               break;
3335           }
3336         }
3337       }
3338       /* Flush MODEs: */
3339       if (cnt > 0 || mblen2 > 1)
3340       {
3341         modebuf[mblen2] = 0;
3342         sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3343             parv[0], chptr->chname, modebuf, parabuf);
3344 #ifndef NO_PROTOCOL9
3345         sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3346             parv[0], chptr->chname, modebuf, parabuf, chptr->creationtime);
3347         ts_sent = 1;
3348 #endif
3349       }
3350 #ifndef NO_PROTOCOL9
3351       else if (send_it && !ts_sent)
3352       {
3353         sendto_lowprot_butone(cptr, 9, ":%s MODE %s + " TIME_T_FMT,
3354             parv[0], chptr->chname, chptr->creationtime);
3355         ts_sent = 1;
3356       }
3357 #endif
3358     }
3359   }
3360
3361   if (wipeout)
3362   {
3363     Link *lp;
3364     Link **ban;
3365     int mode;
3366     char m;
3367     int count = -1;
3368
3369     /* Now cancel all previous simple modes */
3370     if ((prev_mode & MODE_SECRET))
3371       cancel_mode(sptr, chptr, 's', NULL, &count);
3372     if ((prev_mode & MODE_PRIVATE))
3373       cancel_mode(sptr, chptr, 'p', NULL, &count);
3374     if ((prev_mode & MODE_MODERATED))
3375       cancel_mode(sptr, chptr, 'm', NULL, &count);
3376     if ((prev_mode & MODE_TOPICLIMIT))
3377       cancel_mode(sptr, chptr, 't', NULL, &count);
3378     if ((prev_mode & MODE_INVITEONLY))
3379       cancel_mode(sptr, chptr, 'i', NULL, &count);
3380     if ((prev_mode & MODE_NOPRIVMSGS))
3381       cancel_mode(sptr, chptr, 'n', NULL, &count);
3382     if ((prev_mode & MODE_LIMIT))
3383     {
3384       current_mode->limit = 0;
3385       cancel_mode(sptr, chptr, 'l', NULL, &count);
3386     }
3387     if ((prev_mode & MODE_KEY))
3388     {
3389       *current_mode->key = 0;
3390       cancel_mode(sptr, chptr, 'k', prev_key, &count);
3391     }
3392     current_mode->mode &= ~prev_mode;
3393
3394     /* And deop and devoice all net.riders on my side */
3395     mode = CHFL_CHANOP;
3396     m = 'o';
3397     for (;;)
3398     {
3399       for (lp = chptr->members; lp; lp = lp->next)
3400       {
3401         if ((lp->flags & CHFL_BURST_JOINED))
3402           continue;             /* This is not a net.rider from
3403                                    this side of the net.junction */
3404         if ((lp->flags & mode))
3405         {
3406           lp->flags &= ~mode;
3407           if (mode == CHFL_CHANOP)
3408             lp->flags |= CHFL_DEOPPED;
3409           cancel_mode(sptr, chptr, m, lp->value.cptr->name, &count);
3410         }
3411       }
3412       if (mode == CHFL_VOICE)
3413         break;
3414       mode = CHFL_VOICE;
3415       m = 'v';
3416     }
3417
3418     /* And finally wipeout all bans that are left */
3419     for (ban = &chptr->banlist; *ban;)
3420     {
3421       Link *tmp = *ban;
3422       if ((tmp->flags & CHFL_BURST_BAN_WIPEOUT))
3423       {
3424         cancel_mode(sptr, chptr, 'b', tmp->value.ban.banstr, &count);
3425         /* Copied from del_banid(): */
3426         *ban = tmp->next;
3427         RunFree(tmp->value.ban.banstr);
3428         RunFree(tmp->value.ban.who);
3429         free_link(tmp);
3430         /* Erase ban-valid-bit, for channel members that are banned */
3431         for (tmp = chptr->members; tmp; tmp = tmp->next)
3432           if ((tmp->flags & (CHFL_BANNED | CHFL_BANVALID)) ==
3433               (CHFL_BANNED | CHFL_BANVALID))
3434             tmp->flags &= ~CHFL_BANVALID;       /* `tmp' == channel member */
3435       }
3436       else
3437         ban = &tmp->next;
3438     }
3439     /* Also wipeout overlapped bans */
3440     if (!add_banid_not_called)
3441     {
3442       Link *ban;
3443       while ((ban = next_removed_overlapped_ban()))
3444         cancel_mode(sptr, chptr, 'b', ban->value.ban.banstr, &count);
3445     }
3446     cancel_mode(sptr, chptr, 0, NULL, &count);  /* flush */
3447   }
3448
3449   if (send_it && !netride)
3450   {
3451     Link *bl;
3452     int deban;
3453
3454     if (add_banid_not_called || !(bl = next_removed_overlapped_ban()))
3455     {
3456       deban = 0;
3457       bl = chptr->banlist;
3458       *modebuf = '+';
3459     }
3460     else
3461     {
3462       deban = 1;
3463       *modebuf = '-';
3464     }
3465
3466     mblen2 = 1;
3467     pblen2 = 0;
3468     cnt = 0;
3469     for (;;)
3470     {
3471       size_t nblen = 0;
3472       if (bl)
3473         nblen = strlen(bl->value.ban.banstr);
3474       if (cnt == 6 || (!bl && cnt) || pblen2 + nblen + 12 > MODEBUFLEN) /* The last check is to make sure
3475                                                                            that the receiving 2.9 will
3476                                                                            still process this */
3477       {
3478         /* Time to send buffer */
3479         modebuf[mblen2] = 0;
3480         sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3481             parv[0], chptr->chname, modebuf, parabuf);
3482 #ifndef NO_PROTOCOL9
3483         sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s",
3484             parv[0], chptr->chname, modebuf, parabuf);
3485 #endif
3486         *modebuf = deban ? '-' : '+';
3487         mblen2 = 1;
3488         pblen2 = 0;
3489         cnt = 0;
3490       }
3491       if (!bl)                  /* Done ? */
3492         break;
3493       if (deban || (bl->flags & CHFL_BURST_BAN))
3494       {
3495         /* Add ban to buffers and remove it */
3496         modebuf[mblen2++] = 'b';
3497         parabuf[pblen2++] = ' ';
3498         strcpy(parabuf + pblen2, bl->value.ban.banstr);
3499         pblen2 += nblen;
3500         cnt++;
3501         bl->flags &= ~CHFL_BURST_BAN;
3502       }
3503       if (deban)
3504       {
3505         if (!(bl = next_removed_overlapped_ban()))
3506         {
3507           deban = 0;
3508           modebuf[mblen2++] = '+';
3509           bl = chptr->banlist;
3510         }
3511       }
3512       else
3513         bl = bl->next;
3514     }
3515     /* Flush MODE [-b]+b ...: */
3516     if (cnt > 0 || mblen2 > 1)
3517     {
3518       modebuf[mblen2] = 0;
3519       sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3520           parv[0], chptr->chname, modebuf, parabuf);
3521 #ifndef NO_PROTOCOL9
3522       sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3523           parv[0], chptr->chname, modebuf, parabuf, chptr->creationtime);
3524 #endif
3525     }
3526 #ifndef NO_PROTOCOL9
3527     else if (send_it && !ts_sent)
3528       sendto_lowprot_butone(cptr, 9, ":%s MODE %s + " TIME_T_FMT,
3529           parv[0], chptr->chname, chptr->creationtime);
3530 #endif
3531   }
3532
3533   return 0;
3534 }
3535
3536 /*
3537  * m_part
3538  *
3539  * parv[0] = sender prefix
3540  * parv[1] = channel
3541  * parv[parc - 1] = comment
3542  */
3543 int m_part(aClient *cptr, aClient *sptr, int parc, char *parv[])
3544 {
3545   Reg1 aChannel *chptr;
3546   Reg2 Link *lp;
3547   char *p = NULL, *name, pbuf[BUFSIZE];
3548   char *comment = (parc > 2 && !BadPtr(parv[parc - 1])) ? parv[parc - 1] : NULL;
3549
3550   *pbuf = '\0';                 /* Initialize the part buffer... -Kev */
3551
3552   sptr->flags &= ~FLAGS_TS8;
3553
3554   if (parc < 2 || parv[1][0] == '\0')
3555   {
3556     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "PART");
3557     return 0;
3558   }
3559
3560   for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
3561   {
3562     chptr = get_channel(sptr, name, !CREATE);
3563     if (!chptr)
3564     {
3565       sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
3566       continue;
3567     }
3568     if (*name == '&' && !MyUser(sptr))
3569       continue;
3570     /* Do not use IsMember here: zombies must be able to part too */
3571     if (!(lp = find_user_link(chptr->members, sptr)))
3572     {
3573       /* Normal to get when our client did a kick
3574          for a remote client (who sends back a PART),
3575          so check for remote client or not --Run */
3576       if (MyUser(sptr))
3577         sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
3578             chptr->chname);
3579       continue;
3580     }
3581     /* Recreate the /part list for sending to servers */
3582     if (*name != '&')
3583     {
3584       if (*pbuf)
3585         strcat(pbuf, ",");
3586       strcat(pbuf, name);
3587     }
3588     if (can_send(sptr, chptr) != 0)     /* Returns 0 if we CAN send */
3589       comment = NULL;
3590     /* Send part to all clients */
3591     if (!(lp->flags & CHFL_ZOMBIE))
3592     {
3593       if (comment)
3594         sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], chptr->chname,
3595             comment);
3596       else
3597         sendto_channel_butserv(chptr, sptr, PartFmt1, parv[0], chptr->chname);
3598     }
3599     else if (MyUser(sptr))
3600     {
3601       if (comment)
3602         sendto_one(sptr, PartFmt2, parv[0], chptr->chname, comment);
3603       else
3604         sendto_one(sptr, PartFmt1, parv[0], chptr->chname);
3605     }
3606     remove_user_from_channel(sptr, chptr);
3607   }
3608   /* Send out the parts to all servers... -Kev */
3609   if (*pbuf)
3610   {
3611     if (comment)
3612       sendto_serv_butone(cptr, PartFmt2, parv[0], pbuf, comment);
3613     else
3614       sendto_serv_butone(cptr, PartFmt1, parv[0], pbuf);
3615   }
3616   return 0;
3617 }
3618
3619 /*
3620  * m_kick
3621  *
3622  * parv[0] = sender prefix
3623  * parv[1] = channel
3624  * parv[2] = client to kick
3625  * parv[parc-1] = kick comment
3626  */
3627 int m_kick(aClient *cptr, aClient *sptr, int parc, char *parv[])
3628 {
3629   aClient *who;
3630   aChannel *chptr;
3631   char *comment;
3632   Link *lp, *lp2;
3633
3634   sptr->flags &= ~FLAGS_TS8;
3635
3636   if (parc < 3 || *parv[1] == '\0')
3637   {
3638     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KICK");
3639     return 0;
3640   }
3641
3642   if (IsServer(sptr))
3643     send_hack_notice(cptr, sptr, parc, parv, 1, 3);
3644
3645   comment = (BadPtr(parv[parc - 1])) ? parv[0] : parv[parc - 1];
3646   if (strlen(comment) > (size_t)TOPICLEN)
3647     comment[TOPICLEN] = '\0';
3648
3649   *nickbuf = *buf = '\0';
3650
3651   chptr = get_channel(sptr, parv[1], !CREATE);
3652   if (!chptr)
3653   {
3654     sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
3655     return 0;
3656   }
3657   if (IsLocalChannel(parv[1]) && !MyUser(sptr))
3658     return 0;
3659   if (IsModelessChannel(parv[1]))
3660   {
3661     sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
3662         chptr->chname);
3663     return 0;
3664   }
3665   if (!IsServer(cptr) && !is_chan_op(sptr, chptr))
3666   {
3667     sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3668         me.name, parv[0], chptr->chname);
3669     return 0;
3670   }
3671
3672   lp2 = find_user_link(chptr->members, sptr);
3673   if (MyUser(sptr) || Protocol(cptr) < 10)
3674   {
3675     if (!(who = find_chasing(sptr, parv[2], NULL)))
3676       return 0;                 /* No such user left! */
3677   }
3678   else if (!(who = findNUser(parv[2])))
3679     return 0;                   /* No such user left! */
3680   /* if the user is +k, prevent a kick from local user */
3681   if (IsChannelService(who) && MyUser(sptr))
3682   {
3683     sendto_one(sptr, err_str(ERR_ISCHANSERVICE), me.name,
3684         parv[0], who->name, chptr->chname);
3685     return 0;
3686   }
3687 #ifdef NO_OPER_DEOP_LCHAN
3688   /*
3689    * Prevent kicking opers from local channels -DM-
3690    */
3691   if (IsOperOnLocalChannel(who, chptr->chname))
3692   {
3693     sendto_one(sptr, err_str(ERR_ISOPERLCHAN), me.name,
3694                parv[0], who->name, chptr->chname);
3695     return 0;
3696   }
3697 #endif
3698
3699   if (((lp = find_user_link(chptr->members, who)) &&
3700       !(lp->flags & CHFL_ZOMBIE)) || IsServer(sptr))
3701   {
3702     if (who->from != cptr &&
3703         ((lp2 && (lp2->flags & CHFL_DEOPPED)) || (!lp2 && IsUser(sptr))))
3704     {
3705       /*
3706        * Bounce here:
3707        * cptr must be a server (or cptr == sptr and
3708        * sptr->flags can't have DEOPPED set
3709        * when CHANOP is set).
3710        */
3711       sendto_one(cptr, ":%s JOIN %s", who->name, parv[1]);
3712       if (lp->flags & CHFL_CHANOP)
3713       {
3714         if (Protocol(cptr) < 10)
3715           sendto_one(cptr, ":%s MODE %s +o %s " TIME_T_FMT,
3716               me.name, parv[1], who->name, chptr->creationtime);
3717         else
3718           sendto_one(cptr, "%s MODE %s +o %s%s " TIME_T_FMT,
3719               NumServ(&me), parv[1], NumNick(who), chptr->creationtime);
3720       }
3721       if (lp->flags & CHFL_VOICE)
3722       {
3723         if (Protocol(cptr) < 10)
3724           sendto_one(cptr, ":%s MODE %s +v %s " TIME_T_FMT,
3725               me.name, chptr->chname, who->name, chptr->creationtime);
3726         else
3727           sendto_one(cptr, "%s MODE %s +v %s%s " TIME_T_FMT,
3728               NumServ(&me), parv[1], NumNick(who), chptr->creationtime);
3729       }
3730     }
3731     else
3732     {
3733       if (lp)
3734         sendto_channel_butserv(chptr, sptr,
3735             ":%s KICK %s %s :%s", parv[0], chptr->chname, who->name, comment);
3736       if (!IsLocalChannel(parv[1]))
3737       {
3738         sendto_lowprot_butone(cptr, 9, ":%s KICK %s %s :%s",
3739             parv[0], chptr->chname, who->name, comment);
3740         sendto_highprot_butone(cptr, 10, ":%s KICK %s %s%s :%s",
3741             parv[0], parv[1], NumNick(who), comment);
3742       }
3743       if (lp)
3744       {
3745 /*
3746  * Consider:
3747  *
3748  *                     client
3749  *                       |
3750  *                       c
3751  *                       |
3752  *     X --a--> A --b--> B --d--> D
3753  *                       |
3754  *                      who
3755  *
3756  * Where `who' is being KICK-ed by a "KICK" message received by server 'A'
3757  * via 'a', or on server 'B' via either 'b' or 'c', or on server D via 'd'.
3758  *
3759  * a) On server A : set CHFL_ZOMBIE for `who' (lp) and pass on the KICK.
3760  *    Remove the user immedeately when no users are left on the channel.
3761  * b) On server B : remove the user (who/lp) from the channel, send a
3762  *    PART upstream (to A) and pass on the KICK.
3763  * c) KICKed by `client'; On server B : remove the user (who/lp) from the
3764  *    channel, and pass on the KICK.
3765  * d) On server D : remove the user (who/lp) from the channel, and pass on
3766  *    the KICK.
3767  *
3768  * Note:
3769  * - Setting the ZOMBIE flag never hurts, we either remove the
3770  *   client after that or we don't.
3771  * - The KICK message was already passed on, as should be in all cases.
3772  * - `who' is removed in all cases except case a) when users are left.
3773  * - A PART is only sent upstream in case b).
3774  *
3775  * 2 aug 97:
3776  *
3777  *              6
3778  *              |
3779  *  1 --- 2 --- 3 --- 4 --- 5
3780  *        |           |
3781  *      kicker       who
3782  *
3783  * We also need to turn 'who' into a zombie on servers 1 and 6,
3784  * because a KICK from 'who' (kicking someone else in that direction)
3785  * can arrive there afterwards - which should not be bounced itself.
3786  * Therefore case a) also applies for servers 1 and 6.
3787  *
3788  * --Run
3789  */
3790         /* Default for case a): */
3791         lp->flags |= CHFL_ZOMBIE;
3792         /* Case b) or c) ?: */
3793         if (MyUser(who))        /* server 4 */
3794         {
3795           if (IsServer(cptr))   /* Case b) ? */
3796             sendto_one(cptr, PartFmt1, who->name, parv[1]);
3797           remove_user_from_channel(who, chptr);
3798           return 0;
3799         }
3800         if (who->from == cptr)  /* True on servers 1, 5 and 6 */
3801         {
3802           aClient *acptr = IsServer(sptr) ? sptr : sptr->user->server;
3803           for (; acptr != &me; acptr = acptr->serv->up)
3804             if (acptr == who->user->server)     /* Case d) (server 5) */
3805             {
3806               remove_user_from_channel(who, chptr);
3807               return 0;
3808             }
3809         }
3810         /* Case a) (servers 1, 2, 3 and 6) */
3811         for (lp = chptr->members; lp; lp = lp->next)
3812           if (!(lp->flags & CHFL_ZOMBIE))
3813             break;
3814         if (!lp)
3815           remove_user_from_channel(who, chptr);
3816 #ifdef GODMODE
3817         else
3818           sendto_op_mask(SNO_HACK2, "%s is now a zombie on %s",
3819               who->name, chptr->chname);
3820 #endif
3821       }
3822     }
3823   }
3824   else if (MyUser(sptr))
3825     sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
3826         me.name, parv[0], who->name, chptr->chname);
3827
3828   return 0;
3829 }
3830
3831 /*
3832  * m_topic
3833  *
3834  * parv[0]        = sender prefix
3835  * parv[1]        = channel
3836  * parv[parc - 1] = topic (if parc > 2)
3837  */
3838 int m_topic(aClient *cptr, aClient *sptr, int parc, char *parv[])
3839 {
3840   aChannel *chptr;
3841   char *topic = NULL, *name, *p = NULL;
3842
3843   if (parc < 2)
3844   {
3845     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "TOPIC");
3846     return 0;
3847   }
3848
3849   if (parc > 2)
3850     topic = parv[parc - 1];
3851
3852   for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
3853   {
3854     chptr = NULL;
3855     if (!IsChannelName(name) || !(chptr = FindChannel(name)) ||
3856         ((topic || SecretChannel(chptr)) && !IsMember(sptr, chptr)))
3857     {
3858       sendto_one(sptr, err_str(chptr ? ERR_NOTONCHANNEL : ERR_NOSUCHCHANNEL),
3859           me.name, parv[0], chptr ? chptr->chname : name);
3860       continue;
3861     }
3862     if (IsModelessChannel(name))
3863     {
3864       sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
3865           chptr->chname);
3866       continue;
3867     }
3868     if (IsLocalChannel(name) && !MyUser(sptr))
3869       continue;
3870
3871     if (!topic)                 /* only asking  for topic  */
3872     {
3873       if (chptr->topic[0] == '\0')
3874         sendto_one(sptr, rpl_str(RPL_NOTOPIC), me.name, parv[0], chptr->chname);
3875       else
3876       {
3877         sendto_one(sptr, rpl_str(RPL_TOPIC),
3878             me.name, parv[0], chptr->chname, chptr->topic);
3879         sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME),
3880             me.name, parv[0], chptr->chname,
3881             chptr->topic_nick, chptr->topic_time);
3882       }
3883     }
3884     else if (((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
3885         is_chan_op(sptr, chptr)) && topic)
3886     {
3887       /* setting a topic */
3888       strncpy(chptr->topic, topic, TOPICLEN);
3889       strncpy(chptr->topic_nick, sptr->name, NICKLEN);
3890       chptr->topic_time = now;
3891       sendto_serv_butone(cptr, ":%s TOPIC %s :%s",
3892           parv[0], chptr->chname, chptr->topic);
3893       sendto_channel_butserv(chptr, sptr, ":%s TOPIC %s :%s",
3894           parv[0], chptr->chname, chptr->topic);
3895     }
3896     else
3897       sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3898           me.name, parv[0], chptr->chname);
3899   }
3900   return 0;
3901 }
3902
3903 /*
3904  * m_invite
3905  *   parv[0] - sender prefix
3906  *   parv[1] - user to invite
3907  *   parv[2] - channel name
3908  *
3909  * - INVITE now is accepted only if who does it is chanop (this of course
3910  *   implies that channel must exist and he must be on it).
3911  *
3912  * - On the other side it IS processed even if channel is NOT invite only
3913  *   leaving room for other enhancements like inviting banned ppl.  -- Nemesi
3914  *
3915  */
3916 int m_invite(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
3917 {
3918   aClient *acptr;
3919   aChannel *chptr;
3920
3921   if (parc < 3 || *parv[2] == '\0')
3922   {
3923     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "INVITE");
3924     return 0;
3925   }
3926
3927   if (!(acptr = FindUser(parv[1])))
3928   {
3929     sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
3930     return 0;
3931   }
3932
3933   if (is_silenced(sptr, acptr))
3934     return 0;
3935
3936   if (MyUser(sptr))
3937     clean_channelname(parv[2]);
3938   else if (IsLocalChannel(parv[2]))
3939     return 0;
3940
3941   if (*parv[2] == '0' || !IsChannelName(parv[2]))
3942     return 0;
3943
3944   if (!(chptr = FindChannel(parv[2])))
3945   {
3946     if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2]))
3947     {
3948       sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], parv[2]);
3949       return 0;
3950     }
3951
3952     /* Do not disallow to invite to non-existant #channels, otherwise they
3953        would simply first be created, causing only MORE bandwidth usage. */
3954     if (MyConnect(sptr))
3955     {
3956       if (check_target_limit(sptr, acptr, acptr->name, 0))
3957         return 0;
3958
3959       sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
3960           acptr->name, parv[2]);
3961
3962       if (acptr->user->away)
3963         sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
3964             acptr->name, acptr->user->away);
3965     }
3966
3967     sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
3968         acptr->name, parv[2]);
3969
3970     return 0;
3971   }
3972
3973   if (!IsMember(sptr, chptr))
3974   {
3975     sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
3976         chptr->chname);
3977     return 0;
3978   }
3979
3980   if (IsMember(acptr, chptr))
3981   {
3982     sendto_one(sptr, err_str(ERR_USERONCHANNEL),
3983         me.name, parv[0], acptr->name, chptr->chname);
3984     return 0;
3985   }
3986
3987   if (MyConnect(sptr))
3988   {
3989     if (!is_chan_op(sptr, chptr))
3990     {
3991       sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3992           me.name, parv[0], chptr->chname);
3993       return 0;
3994     }
3995
3996     /* If we get here, it was a VALID and meaningful INVITE */
3997
3998     if (check_target_limit(sptr, acptr, acptr->name, 0))
3999       return 0;
4000
4001     sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
4002         acptr->name, chptr->chname);
4003
4004     if (acptr->user->away)
4005       sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
4006           acptr->name, acptr->user->away);
4007   }
4008
4009   if (MyConnect(acptr))
4010     add_invite(acptr, chptr);
4011
4012   sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
4013       acptr->name, chptr->chname);
4014
4015   return 0;
4016 }
4017
4018 static int number_of_zombies(aChannel *chptr)
4019 {
4020   Reg1 Link *lp;
4021   Reg2 int count = 0;
4022   for (lp = chptr->members; lp; lp = lp->next)
4023     if (lp->flags & CHFL_ZOMBIE)
4024       count++;
4025   return count;
4026 }
4027
4028 /*
4029  * m_list
4030  *
4031  * parv[0] = sender prefix
4032  * parv[1] = channel list or user/time limit
4033  * parv[2...] = more user/time limits
4034  */
4035 int m_list(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
4036 {
4037   aChannel *chptr;
4038   char *name, *p = NULL;
4039   int show_usage = 0, show_channels = 0, param;
4040   aListingArgs args = {
4041     2147483647,                 /* max_time */
4042     0,                          /* min_time */
4043     4294967295U,                /* max_users */
4044     0,                          /* min_users */
4045     0,                          /* topic_limits */
4046     2147483647,                 /* max_topic_time */
4047     0,                          /* min_topic_time */
4048     NULL                        /* chptr */
4049   };
4050
4051   if (sptr->listing)            /* Already listing ? */
4052   {
4053     sptr->listing->chptr->mode.mode &= ~MODE_LISTED;
4054     RunFree(sptr->listing);
4055     sptr->listing = NULL;
4056     sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, sptr->name);
4057     if (parc < 2)
4058       return 0;                 /* Let LIST abort a listing. */
4059   }
4060
4061   if (parc < 2)                 /* No arguments given to /LIST ? */
4062   {
4063 #ifdef DEFAULT_LIST_PARAM
4064     static char *defparv[MAXPARA + 1];
4065     static int defparc = 0;
4066     static char lp[] = DEFAULT_LIST_PARAM;
4067     int i;
4068
4069     if (!defparc)
4070     {
4071       char *s = lp, *t;
4072
4073       defparc = 1;
4074       defparv[defparc++] = t = strtok(s, " ");
4075       while (t && defparc < MAXPARA)
4076       {
4077         if ((t = strtok(NULL, " ")))
4078           defparv[defparc++] = t;
4079       }
4080     }
4081     for (i = 1; i < defparc; i++)
4082       parv[i] = defparv[i];
4083     parv[i] = NULL;
4084     parc = defparc;
4085 #endif /* DEFAULT_LIST_PARAM */
4086   }
4087
4088   /* Decode command */
4089   for (param = 1; !show_usage && parv[param]; param++)
4090   {
4091     char *p = parv[param];
4092     do
4093     {
4094       int is_time = 0;
4095       switch (*p)
4096       {
4097         case 'T':
4098         case 't':
4099           is_time++;
4100           args.topic_limits = 1;
4101           /* Fall through */
4102         case 'C':
4103         case 'c':
4104           is_time++;
4105           p++;
4106           if (*p != '<' && *p != '>')
4107           {
4108             show_usage = 1;
4109             break;
4110           }
4111           /* Fall through */
4112         case '<':
4113         case '>':
4114         {
4115           p++;
4116           if (!isDigit(*p))
4117             show_usage = 1;
4118           else
4119           {
4120             if (is_time)
4121             {
4122               time_t val = atoi(p);
4123               if (p[-1] == '<')
4124               {
4125                 if (val < 80000000)     /* Toggle UTC/offset */
4126                 {
4127                   /*
4128                    * Demands that
4129                    * 'TStime() - chptr->creationtime < val * 60'
4130                    * Which equals
4131                    * 'chptr->creationtime > TStime() - val * 60'
4132                    */
4133                   if (is_time == 1)
4134                     args.min_time = TStime() - val * 60;
4135                   else
4136                     args.min_topic_time = TStime() - val * 60;
4137                 }
4138                 else if (is_time == 1)  /* Creation time in UTC was entered */
4139                   args.max_time = val;
4140                 else            /* Topic time in UTC was entered */
4141                   args.max_topic_time = val;
4142               }
4143               else if (val < 80000000)
4144               {
4145                 if (is_time == 1)
4146                   args.max_time = TStime() - val * 60;
4147                 else
4148                   args.max_topic_time = TStime() - val * 60;
4149               }
4150               else if (is_time == 1)
4151                 args.min_time = val;
4152               else
4153                 args.min_topic_time = val;
4154             }
4155             else if (p[-1] == '<')
4156               args.max_users = atoi(p);
4157             else
4158               args.min_users = atoi(p);
4159             if ((p = strchr(p, ',')))
4160               p++;
4161           }
4162           break;
4163         }
4164         default:
4165           if (!IsChannelName(p))
4166           {
4167             show_usage = 1;
4168             break;
4169           }
4170           if (parc != 2)        /* Don't allow a mixture of channels with <,> */
4171             show_usage = 1;
4172           show_channels = 1;
4173           p = NULL;
4174           break;
4175       }
4176     }
4177     while (!show_usage && p);   /* p points after comma, or is NULL */
4178   }
4179
4180   if (show_usage)
4181   {
4182     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4183         "Usage: \002/QUOTE LIST\002 \037parameters\037");
4184     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4185         "Where \037parameters\037 is a space or comma seperated "
4186         "list of one or more of:");
4187     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4188         " \002<\002\037max_users\037    ; Show all channels with less "
4189         "than \037max_users\037.");
4190     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4191         " \002>\002\037min_users\037    ; Show all channels with more "
4192         "than \037min_users\037.");
4193     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4194         " \002C<\002\037max_minutes\037 ; Channels that exist less "
4195         "than \037max_minutes\037.");
4196     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4197         " \002C>\002\037min_minutes\037 ; Channels that exist more "
4198         "than \037min_minutes\037.");
4199     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4200         " \002T<\002\037max_minutes\037 ; Channels with a topic last "
4201         "set less than \037max_minutes\037 ago.");
4202     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4203         " \002T>\002\037min_minutes\037 ; Channels with a topic last "
4204         "set more than \037min_minutes\037 ago.");
4205     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4206         "Example: LIST <3,>1,C<10,T>0  ; 2 users, younger than 10 min., "
4207         "topic set.");
4208     return 0;
4209   }
4210
4211   sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, parv[0]);
4212
4213   if (!show_channels)
4214   {
4215     if (args.max_users > args.min_users + 1 && args.max_time > args.min_time &&
4216         args.max_topic_time > args.min_topic_time)      /* Sanity check */
4217     {
4218       if ((sptr->listing = (aListingArgs *)RunMalloc(sizeof(aListingArgs))))
4219       {
4220         memcpy(sptr->listing, &args, sizeof(aListingArgs));
4221         if ((sptr->listing->chptr = channel))
4222         {
4223           int m = channel->mode.mode & MODE_LISTED;
4224           list_next_channels(sptr, 64);
4225           channel->mode.mode |= m;
4226           return 0;
4227         }
4228         RunFree(sptr->listing);
4229         sptr->listing = NULL;
4230       }
4231     }
4232     sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
4233     return 0;
4234   }
4235
4236   for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
4237   {
4238     chptr = FindChannel(name);
4239     if (chptr && ShowChannel(sptr, chptr) && sptr->user)
4240       sendto_one(sptr, rpl_str(RPL_LIST), me.name, parv[0],
4241           ShowChannel(sptr, chptr) ? chptr->chname : "*",
4242           chptr->users - number_of_zombies(chptr), chptr->topic);
4243   }
4244
4245   sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
4246   return 0;
4247 }
4248
4249 /*
4250  * m_names                              - Added by Jto 27 Apr 1989
4251  *
4252  * parv[0] = sender prefix
4253  * parv[1] = channel
4254  */
4255 int m_names(aClient *cptr, aClient *sptr, int parc, char *parv[])
4256 {
4257   Reg1 aChannel *chptr;
4258   Reg2 aClient *c2ptr;
4259   Reg3 Link *lp;
4260   aChannel *ch2ptr = NULL;
4261   int idx, flag, len, mlen;
4262   char *s, *para = parc > 1 ? parv[1] : NULL;
4263
4264   if (parc > 2 && hunt_server(1, cptr, sptr, ":%s NAMES %s %s", 2, parc, parv))
4265     return 0;
4266
4267   mlen = strlen(me.name) + 10 + strlen(sptr->name);
4268
4269   if (!BadPtr(para))
4270   {
4271     s = strchr(para, ',');
4272     if (s)
4273     {
4274       parv[1] = ++s;
4275       m_names(cptr, sptr, parc, parv);
4276     }
4277     clean_channelname(para);
4278     ch2ptr = FindChannel(para);
4279   }
4280
4281   /*
4282    * First, do all visible channels (public and the one user self is)
4283    */
4284
4285   for (chptr = channel; chptr; chptr = chptr->nextch)
4286   {
4287     if ((chptr != ch2ptr) && !BadPtr(para))
4288       continue;                 /* -- wanted a specific channel */
4289     if (!MyConnect(sptr) && BadPtr(para))
4290       continue;
4291 #ifndef GODMODE
4292     if (!ShowChannel(sptr, chptr))
4293       continue;                 /* -- users on this are not listed */
4294 #endif
4295
4296     /* Find users on same channel (defined by chptr) */
4297
4298     strcpy(buf, "* ");
4299     len = strlen(chptr->chname);
4300     strcpy(buf + 2, chptr->chname);
4301     strcpy(buf + 2 + len, " :");
4302
4303     if (PubChannel(chptr))
4304       *buf = '=';
4305     else if (SecretChannel(chptr))
4306       *buf = '@';
4307     idx = len + 4;
4308     flag = 1;
4309     for (lp = chptr->members; lp; lp = lp->next)
4310     {
4311       c2ptr = lp->value.cptr;
4312 #ifndef GODMODE
4313       if (sptr != c2ptr && IsInvisible(c2ptr) && !IsMember(sptr, chptr))
4314         continue;
4315 #endif
4316       if (lp->flags & CHFL_ZOMBIE)
4317       {
4318         if (lp->value.cptr != sptr)
4319           continue;
4320         else
4321         {
4322           strcat(buf, "!");
4323           idx++;
4324         }
4325       }
4326       else if (lp->flags & CHFL_CHANOP)
4327       {
4328         strcat(buf, "@");
4329         idx++;
4330       }
4331       else if (lp->flags & CHFL_VOICE)
4332       {
4333         strcat(buf, "+");
4334         idx++;
4335       }
4336       strcat(buf, c2ptr->name);
4337       strcat(buf, " ");
4338       idx += strlen(c2ptr->name) + 1;
4339       flag = 1;
4340 #ifdef GODMODE
4341       {
4342         char yxx[6];
4343         sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
4344         if (c2ptr != findNUser(yxx))
4345           MyCoreDump;
4346         sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
4347         idx += 6;
4348       }
4349       if (mlen + idx + NICKLEN + 11 > BUFSIZE)
4350 #else
4351       if (mlen + idx + NICKLEN + 5 > BUFSIZE)
4352 #endif
4353         /* space, modifier, nick, \r \n \0 */
4354       {
4355         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4356         strcpy(buf, "* ");
4357         strncpy(buf + 2, chptr->chname, len + 1);
4358         buf[len + 2] = 0;
4359         strcat(buf, " :");
4360         if (PubChannel(chptr))
4361           *buf = '=';
4362         else if (SecretChannel(chptr))
4363           *buf = '@';
4364         idx = len + 4;
4365         flag = 0;
4366       }
4367     }
4368     if (flag)
4369       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4370   }
4371   if (!BadPtr(para))
4372   {
4373     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
4374         ch2ptr ? ch2ptr->chname : para);
4375     return (1);
4376   }
4377
4378   /* Second, do all non-public, non-secret channels in one big sweep */
4379
4380   strcpy(buf, "* * :");
4381   idx = 5;
4382   flag = 0;
4383   for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
4384   {
4385     aChannel *ch3ptr;
4386     int showflag = 0, secret = 0;
4387
4388 #ifndef GODMODE
4389     if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
4390 #else
4391     if (!IsUser(c2ptr))
4392 #endif
4393       continue;
4394     lp = c2ptr->user->channel;
4395     /*
4396      * Don't show a client if they are on a secret channel or when
4397      * they are on a channel sptr is on since they have already
4398      * been show earlier. -avalon
4399      */
4400     while (lp)
4401     {
4402       ch3ptr = lp->value.chptr;
4403 #ifndef GODMODE
4404       if (PubChannel(ch3ptr) || IsMember(sptr, ch3ptr))
4405 #endif
4406         showflag = 1;
4407       if (SecretChannel(ch3ptr))
4408         secret = 1;
4409       lp = lp->next;
4410     }
4411     if (showflag)               /* Have we already shown them ? */
4412       continue;
4413 #ifndef GODMODE
4414     if (secret)                 /* On any secret channels ? */
4415       continue;
4416 #endif
4417     strcat(buf, c2ptr->name);
4418     strcat(buf, " ");
4419     idx += strlen(c2ptr->name) + 1;
4420     flag = 1;
4421 #ifdef GODMODE
4422     {
4423       char yxx[6];
4424       sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
4425       if (c2ptr != findNUser(yxx))
4426         MyCoreDump;
4427       sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
4428       idx += 6;
4429     }
4430 #endif
4431 #ifdef GODMODE
4432     if (mlen + idx + NICKLEN + 9 > BUFSIZE)
4433 #else
4434     if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
4435 #endif
4436     {
4437       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4438       strcpy(buf, "* * :");
4439       idx = 5;
4440       flag = 0;
4441     }
4442   }
4443   if (flag)
4444     sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4445   sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
4446   return (1);
4447 }
4448
4449 void send_user_joins(aClient *cptr, aClient *user)
4450 {
4451   Reg1 Link *lp;
4452   Reg2 aChannel *chptr;
4453   Reg3 int cnt = 0, len = 0, clen;
4454   char *mask;
4455
4456   *buf = ':';
4457   strcpy(buf + 1, user->name);
4458   strcat(buf, " JOIN ");
4459   len = strlen(user->name) + 7;
4460
4461   for (lp = user->user->channel; lp; lp = lp->next)
4462   {
4463     chptr = lp->value.chptr;
4464     if ((mask = strchr(chptr->chname, ':')))
4465       if (match(++mask, cptr->name))
4466         continue;
4467     if (*chptr->chname == '&')
4468       continue;
4469     if (is_zombie(user, chptr))
4470       continue;
4471     clen = strlen(chptr->chname);
4472     if (clen + 1 + len > BUFSIZE - 3)
4473     {
4474       if (cnt)
4475       {
4476         buf[len - 1] = '\0';
4477         sendto_one(cptr, "%s", buf);
4478       }
4479       *buf = ':';
4480       strcpy(buf + 1, user->name);
4481       strcat(buf, " JOIN ");
4482       len = strlen(user->name) + 7;
4483       cnt = 0;
4484     }
4485     strcpy(buf + len, chptr->chname);
4486     cnt++;
4487     len += clen;
4488     if (lp->next)
4489     {
4490       len++;
4491       strcat(buf, ",");
4492     }
4493   }
4494   if (*buf && cnt)
4495     sendto_one(cptr, "%s", buf);
4496
4497   return;
4498 }
4499
4500 /*
4501  * send_hack_notice()
4502  *
4503  * parc & parv[] are the same as that of the calling function:
4504  *   mtype == 1 is from m_mode, 2 is from m_create, 3 is from m_kick.
4505  *
4506  * This function prepares sendbuf with the server notices and wallops
4507  *   to be sent for all hacks.  -Ghostwolf 18-May-97
4508  */
4509
4510 static void send_hack_notice(aClient *cptr, aClient *sptr, int parc,
4511     char *parv[], int badop, int mtype)
4512 {
4513   aChannel *chptr;
4514   static char params[MODEBUFLEN];
4515   int i = 3;
4516   chptr = FindChannel(parv[1]);
4517   *params = '\0';
4518
4519   if (Protocol(cptr) < 10)      /* We don't get numeric nicks from P09  */
4520   {                             /* servers, so this can be sent "As Is" */
4521     if (mtype == 1)
4522     {
4523       while (i < parc)
4524       {
4525         strcat(params, " ");
4526         strcat(params, parv[i++]);
4527       }
4528       sprintf_irc(sendbuf,
4529           ":%s NOTICE * :*** Notice -- %sHACK(%d): %s MODE %s %s%s [" TIME_T_FMT
4530           "]", me.name, (badop == 3) ? "BOUNCE or " : "", badop, parv[0],
4531           parv[1], parv[2], params, chptr->creationtime);
4532       sendbufto_op_mask((badop == 3) ? SNO_HACK3 : (badop ==
4533           4) ? SNO_HACK4 : SNO_HACK2);
4534
4535       if ((IsServer(sptr)) && (badop == 2))
4536       {
4537         sprintf_irc(sendbuf, ":%s DESYNCH :HACK: %s MODE %s %s%s",
4538             me.name, parv[0], parv[1], parv[2], params);
4539         sendbufto_serv_butone(cptr);
4540       }
4541     }
4542     else if (mtype == 3)
4543     {
4544       sprintf_irc(sendbuf,
4545           ":%s NOTICE * :*** Notice -- HACK: %s KICK %s %s :%s",
4546           me.name, sptr->name, parv[1], parv[2], parv[3]);
4547       sendbufto_op_mask(SNO_HACK4);
4548     }
4549   }
4550   else
4551   {
4552     /* P10 servers require numeric nick conversion before sending. */
4553     switch (mtype)
4554     {
4555       case 1:                   /* Convert nicks for MODE HACKs here  */
4556       {
4557         char *mode = parv[2];
4558         while (i < parc)
4559         {
4560           while (*mode && *mode != 'o' && *mode != 'v')
4561             ++mode;
4562           strcat(params, " ");
4563           if (*mode == 'o' || *mode == 'v')
4564           {
4565             register aClient *acptr;
4566             if ((acptr = findNUser(parv[i])) != NULL)   /* Convert nicks here */
4567               strcat(params, acptr->name);
4568             else
4569             {
4570               strcat(params, "<");
4571               strcat(params, parv[i]);
4572               strcat(params, ">");
4573             }
4574           }
4575           else                  /* If it isn't a numnick, send it 'as is' */
4576             strcat(params, parv[i]);
4577           i++;
4578         }
4579         sprintf_irc(sendbuf,
4580             ":%s NOTICE * :*** Notice -- %sHACK(%d): %s MODE %s %s%s ["
4581             TIME_T_FMT "]", me.name, (badop == 3) ? "BOUNCE or " : "", badop,
4582             parv[0], parv[1], parv[2], params, chptr->creationtime);
4583         sendbufto_op_mask((badop == 3) ? SNO_HACK3 : (badop ==
4584             4) ? SNO_HACK4 : SNO_HACK2);
4585
4586         if ((IsServer(sptr)) && (badop == 2))
4587         {
4588           sprintf_irc(sendbuf, ":%s DESYNCH :HACK: %s MODE %s %s%s",
4589               me.name, parv[0], parv[1], parv[2], params);
4590           sendbufto_serv_butone(cptr);
4591         }
4592         break;
4593       }
4594       case 2:                   /* No conversion is needed for CREATE; the only numnick is sptr */
4595       {
4596         sendto_serv_butone(cptr, ":%s DESYNCH :HACK: %s CREATE %s %s",
4597             me.name, sptr->name, chptr->chname, parv[2]);
4598         sendto_op_mask(SNO_HACK2, "HACK(2): %s CREATE %s %s",
4599             sptr->name, chptr->chname, parv[2]);
4600         break;
4601       }
4602       case 3:                   /* Convert nick in KICK message */
4603       {
4604         aClient *acptr;
4605         if ((acptr = findNUser(parv[2])) != NULL)       /* attempt to convert nick */
4606           sprintf_irc(sendbuf,
4607               ":%s NOTICE * :*** Notice -- HACK: %s KICK %s %s :%s",
4608               me.name, sptr->name, parv[1], acptr->name, parv[3]);
4609         else                    /* if conversion fails, send it 'as is' in <>'s */
4610           sprintf_irc(sendbuf,
4611               ":%s NOTICE * :*** Notice -- HACK: %s KICK %s <%s> :%s",
4612               me.name, sptr->name, parv[1], parv[2], parv[3]);
4613         sendbufto_op_mask(SNO_HACK4);
4614         break;
4615       }
4616     }
4617   }
4618 }