Author: Bleep <tomh@inxpress.net>
[ircu2.10.12-pk.git] / ircd / m_burst.c
1 /*
2  * IRC - Internet Relay Chat, ircd/m_burst.c
3  * Copyright (C) 1990 Jarkko Oikarinen and
4  *                    University of Oulu, Computing Center
5  *
6  * See file AUTHORS in IRC package for additional names of
7  * the programmers.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 1, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  * $Id$
24  */
25
26 /*
27  * m_functions execute protocol messages on this server:
28  *
29  *    cptr    is always NON-NULL, pointing to a *LOCAL* client
30  *            structure (with an open socket connected!). This
31  *            identifies the physical socket where the message
32  *            originated (or which caused the m_function to be
33  *            executed--some m_functions may call others...).
34  *
35  *    sptr    is the source of the message, defined by the
36  *            prefix part of the message if present. If not
37  *            or prefix not found, then sptr==cptr.
38  *
39  *            (!IsServer(cptr)) => (cptr == sptr), because
40  *            prefixes are taken *only* from servers...
41  *
42  *            (IsServer(cptr))
43  *                    (sptr == cptr) => the message didn't
44  *                    have the prefix.
45  *
46  *                    (sptr != cptr && IsServer(sptr) means
47  *                    the prefix specified servername. (?)
48  *
49  *                    (sptr != cptr && !IsServer(sptr) means
50  *                    that message originated from a remote
51  *                    user (not local).
52  *
53  *            combining
54  *
55  *            (!IsServer(sptr)) means that, sptr can safely
56  *            taken as defining the target structure of the
57  *            message in this server.
58  *
59  *    *Always* true (if 'parse' and others are working correct):
60  *
61  *    1)      sptr->from == cptr  (note: cptr->from == cptr)
62  *
63  *    2)      MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64  *            *cannot* be a local connection, unless it's
65  *            actually cptr!). [MyConnect(x) should probably
66  *            be defined as (x == x->from) --msa ]
67  *
68  *    parc    number of variable parameter strings (if zero,
69  *            parv is allowed to be NULL)
70  *
71  *    parv    a NULL terminated list of parameter pointers,
72  *
73  *                    parv[0], sender (prefix string), if not present
74  *                            this points to an empty string.
75  *                    parv[1]...parv[parc-1]
76  *                            pointers to additional parameters
77  *                    parv[parc] == NULL, *always*
78  *
79  *            note:   it is guaranteed that parv[0]..parv[parc-1] are all
80  *                    non-NULL pointers.
81  */
82 #if 0
83 /*
84  * No need to include handlers.h here the signatures must match
85  * and we don't need to force a rebuild of all the handlers everytime
86  * we add a new one to the list. --Bleep
87  */
88 #include "handlers.h"
89 #endif /* 0 */
90 #include "channel.h"
91 #include "client.h"
92 #include "hash.h"
93 #include "ircd.h"
94 #include "ircd_alloc.h"
95 #include "ircd_reply.h"
96 #include "ircd_string.h"
97 #include "list.h"
98 #include "msg.h"
99 #include "numeric.h"
100 #include "numnicks.h"
101 #include "s_conf.h"
102 #include "s_misc.h"
103 #include "send.h"
104 #include "struct.h"
105
106 #include <assert.h>
107 #include <stdlib.h>
108 #include <string.h>
109
110 /*
111  * ms_burst - server message handler
112  *
113  * --  by Run carlo@runaway.xs4all.nl  december 1995 till march 1997
114  *
115  * parv[0] = sender prefix
116  * parv[1] = channel name
117  * parv[2] = channel timestamp
118  * The meaning of the following parv[]'s depend on their first character:
119  * If parv[n] starts with a '+':
120  * Net burst, additive modes
121  *   parv[n] = <mode>
122  *   parv[n+1] = <param> (optional)
123  *   parv[n+2] = <param> (optional)
124  * If parv[n] starts with a '%', then n will be parc-1:
125  *   parv[n] = %<ban> <ban> <ban> ...
126  * If parv[n] starts with another character:
127  *   parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
128  *   where <mode> is the channel mode (ov) of nick and all following nicks.
129  *
130  * Example:
131  * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
132  *
133  * Anti net.ride code.
134  *
135  * When the channel already exist, and its TS is larger then
136  * the TS in the BURST message, then we cancel all existing modes.
137  * If its is smaller then the received BURST message is ignored.
138  * If it's equal, then the received modes are just added.
139  */
140 int ms_burst(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
141 {
142   struct Channel* chptr;
143   time_t          timestamp;
144   int             netride = 0;
145   int             wipeout = 0;
146   int             n;
147   int             send_it = 0;
148   int             add_banid_not_called = 1;
149   struct Mode*    current_mode;
150   size_t          sblen;
151   size_t          mblen = 0;
152   int             mblen2;
153   int             pblen2;
154   int             cnt;
155   int             prev_mode;
156   char            prev_key[KEYLEN + 1];
157   struct Membership* member;
158   struct SLink*   lp;
159   char modebuf[MODEBUFLEN];
160   char parabuf[MODEBUFLEN];
161   char bmodebuf[MODEBUFLEN];
162   char bparambuf[MODEBUFLEN];
163
164   /* BURST is only for servers and has at least 4 parameters */
165   if (!IsServer(cptr) || parc < 4)
166     return 0;
167
168   if (!IsBurst(sptr))
169   {
170     int i;
171     char *p;
172     if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD))
173     {
174       p =
175           sprintf_irc(sendbuf,
176           ":%s NOTICE * :*** Notice -- HACK(4): %s BURST %s %s", me.name,
177           sptr->name, parv[1], parv[2]);
178       for (i = 3; i < parc - 1; ++i)
179         p = sprintf_irc(p, " %s", parv[i]);
180       sprintf_irc(p, " :%s", parv[parc - 1]);
181       sendbufto_op_mask(SNO_HACK4);
182     }
183     else
184     {
185 #if 1                           /* FIXME: This should be removed after all HUBs upgraded to ircu2.10.05 */
186       SetBurst(sptr);
187       if (MyConnect(sptr))
188 #endif
189         return exit_client_msg(cptr, cptr, &me,
190             "HACK: BURST message outside net.burst from %s", sptr->name);
191     }
192   }
193
194   /* Find the channel, or create it - note that the creation time
195    * will be 0 if it has to be created */
196   chptr = get_channel(sptr, parv[1], CGT_CREATE);
197   current_mode = &chptr->mode;
198   prev_mode = chptr->mode.mode;
199   if (*chptr->mode.key)
200   {
201     prev_mode |= MODE_KEY;
202     strcpy(prev_key, chptr->mode.key);
203   }
204   if (chptr->mode.limit)
205     prev_mode |= MODE_LIMIT;
206
207   timestamp = atoi(parv[2]);
208
209   /* Copy the new TS when the received creationtime appears to be older */
210   if (!chptr->creationtime || chptr->creationtime > timestamp)
211   {
212     /* Set the new timestamp */
213     chptr->creationtime = timestamp;
214     send_it = 1;                /* Make sure we pass on the different timestamp ! */
215     /* Mark all bans as needed to be wiped out */
216     for (lp = chptr->banlist; lp; lp = lp->next)
217       lp->flags |= CHFL_BURST_BAN_WIPEOUT;
218     /*
219      * Only the first BURST for this channel can have creationtime > timestamp,
220      * so at this moment ALL members are on OUR side, and thus all net.riders:
221      */
222     wipeout = 1;
223   }
224   for (member = chptr->members; member; member = member->next_member)
225     member->status &= ~CHFL_BURST_JOINED;    /* Set later for nicks in the BURST msg */
226   /* If `wipeout' is set then these will be deopped later. */
227
228   /* If the entering creationtime is younger, ignore the modes */
229   if (chptr->creationtime < timestamp)
230     netride = 1;                /* Only pass on the nicks (so they JOIN) */
231
232   /* Prepare buffers to pass the message */
233   *bparambuf = *bmodebuf = *parabuf = '\0';
234   pblen2 = 0;
235   *modebuf = '+';
236   mblen2 = 1;
237   cnt = 0;
238   sblen = sprintf_irc(sendbuf, "%s B %s " TIME_T_FMT,
239       NumServ(sptr), chptr->chname, chptr->creationtime) - sendbuf;
240
241   /* Run over all remaining parameters */
242   for (n = 3; n < parc; n++)
243     switch (*parv[n])           /* What type is it ? mode, nicks or bans ? */
244     {
245       case '+':         /* modes */
246       {
247         char *p = parv[n];
248         while (*(++p))          /* Run over all mode characters */
249         {
250           switch (*p)           /* which mode ? */
251           {
252               /*
253                * The following cases all do the following:
254                * - In case wipeout needed, reset 'prev_mode' to indicate this
255                *   mode should not be cancelled.
256                * - If wipeout or (not netride and the new mode is a change),
257                *   add it to bmodebuf and bparabuf for propagation.
258                * - Else ignore it.
259                * - Add it to modebuf and parabuf for propagation to the
260                *   clients when not netride and the new mode is a change.
261                * Special cases:
262                * - If a +s is received, cancel a +p and sent a -p to the
263                *   clients too (if +p was set).
264                * - If a +p is received and +s is set, ignore the +p.
265                */
266             case 'i':
267             {
268               int tmp;
269               prev_mode &= ~MODE_INVITEONLY;
270               if (!(tmp = netride ||
271                   (current_mode->mode & MODE_INVITEONLY)) || wipeout)
272               {
273                 bmodebuf[mblen++] = 'i';
274                 current_mode->mode |= MODE_INVITEONLY;
275               }
276               if (!tmp)
277                 modebuf[mblen2++] = 'i';
278               break;
279             }
280             case 'k':
281             {
282               int tmp;
283               char *param = parv[++n];
284               prev_mode &= ~MODE_KEY;
285               if (!(tmp = netride || (*current_mode->key &&
286                   (!strcmp(current_mode->key, param) ||
287                   (!wipeout && strcmp(current_mode->key, param) < 0)))) ||
288                   wipeout)
289               {
290                 bmodebuf[mblen++] = 'k';
291                 strcat(bparambuf, " ");
292                 strcat(bparambuf, param);
293                 ircd_strncpy(current_mode->key, param, KEYLEN);
294               }
295               if (!tmp && !wipeout)
296               {
297                 modebuf[mblen2++] = 'k';
298                 parabuf[pblen2++] = ' ';
299                 strcpy(parabuf + pblen2, param);
300                 pblen2 += strlen(param);
301                 cnt++;
302               }
303               break;
304             }
305             case 'l':
306             {
307               int tmp;
308               unsigned int param = atoi(parv[++n]);
309               prev_mode &= ~MODE_LIMIT;
310               if (!(tmp = netride || (current_mode->limit &&
311                   (current_mode->limit == param ||
312                   (!wipeout && current_mode->limit < param)))) || wipeout)
313               {
314                 bmodebuf[mblen++] = 'l';
315                 sprintf_irc(bparambuf + strlen(bparambuf), " %d", param);
316                 current_mode->limit = param;
317               }
318               if (!tmp)
319               {
320                 modebuf[mblen2++] = 'l';
321                 pblen2 = sprintf_irc(parabuf + pblen2, " %d", param) - parabuf;
322                 cnt++;
323               }
324               break;
325             }
326             case 'm':
327             {
328               int tmp;
329               prev_mode &= ~MODE_MODERATED;
330               if (!(tmp = netride ||
331                   (current_mode->mode & MODE_MODERATED)) || wipeout)
332               {
333                 bmodebuf[mblen++] = 'm';
334                 current_mode->mode |= MODE_MODERATED;
335               }
336               if (!tmp)
337                 modebuf[mblen2++] = 'm';
338               break;
339             }
340             case 'n':
341             {
342               int tmp;
343               prev_mode &= ~MODE_NOPRIVMSGS;
344               if (!(tmp = netride ||
345                   (current_mode->mode & MODE_NOPRIVMSGS)) || wipeout)
346               {
347                 bmodebuf[mblen++] = 'n';
348                 current_mode->mode |= MODE_NOPRIVMSGS;
349               }
350               if (!tmp)
351                 modebuf[mblen2++] = 'n';
352               break;
353             }
354             case 'p':
355             {
356               int tmp;
357
358               /* Special case: */
359               if (!netride && !wipeout && (current_mode->mode & MODE_SECRET))
360                 break;
361
362               prev_mode &= ~MODE_PRIVATE;
363               if (!(tmp = netride ||
364                   (current_mode->mode & MODE_PRIVATE)) || wipeout)
365               {
366                 bmodebuf[mblen++] = 'p';
367                 current_mode->mode |= MODE_PRIVATE;
368               }
369               if (!tmp)
370                 modebuf[mblen2++] = 'p';
371               break;
372             }
373             case 's':
374             {
375               int tmp;
376               prev_mode &= ~MODE_SECRET;
377               if (!(tmp = netride ||
378                   (current_mode->mode & MODE_SECRET)) || wipeout)
379               {
380                 bmodebuf[mblen++] = 's';
381                 current_mode->mode |= MODE_SECRET;
382               }
383               if (!tmp)
384                 modebuf[mblen2++] = 's';
385
386               /* Special case: */
387               if (!netride && !wipeout && (current_mode->mode & MODE_PRIVATE))
388               {
389                 int i;
390                 for (i = mblen2 - 1; i >= 0; --i)
391                   modebuf[i + 2] = modebuf[i];
392                 modebuf[0] = '-';
393                 modebuf[1] = 'p';
394                 mblen2 += 2;
395                 current_mode->mode &= ~MODE_PRIVATE;
396               }
397
398               break;
399             }
400             case 't':
401             {
402               int tmp;
403               prev_mode &= ~MODE_TOPICLIMIT;
404               if (!(tmp = netride ||
405                   (current_mode->mode & MODE_TOPICLIMIT)) || wipeout)
406               {
407                 bmodebuf[mblen++] = 't';
408                 current_mode->mode |= MODE_TOPICLIMIT;
409               }
410               if (!tmp)
411                 modebuf[mblen2++] = 't';
412               break;
413             }
414           }
415         }                       /* <-- while over all modes */
416
417         bmodebuf[mblen] = '\0';
418         sendbuf[sblen] = '\0';
419         if (mblen)              /* Anything to send at all ? */
420         {
421           send_it = 1;
422           strcpy(sendbuf + sblen, " +");
423           sblen += 2;
424           strcpy(sendbuf + sblen, bmodebuf);
425           sblen += mblen;
426           strcpy(sendbuf + sblen, bparambuf);
427           sblen += strlen(bparambuf);
428         }
429         break;                  /* Done mode part */
430       }
431       case '%':         /* bans */
432       {
433         char *pv, *p = 0, *ban;
434         int first = 1;
435         if (netride)
436           break;                /* Ignore bans */
437         /* Run over all bans */
438         for (pv = parv[n] + 1; (ban = ircd_strtok(&p, pv, " ")); pv = 0)
439         {
440           int ret;
441           /*
442            * The following part should do the following:
443            * - If the new (un)ban is not a _change_ it is ignored.
444            * - Else, add it to sendbuf for later use.
445            * - If sendbuf is full, send it, and prepare a new
446            *   message in sendbuf.
447            */
448           ret = add_banid(sptr, chptr, ban, 1, add_banid_not_called);
449           if (ret == 0)
450           {
451             add_banid_not_called = 0;
452             /* Mark this new ban so we can send it to the clients later */
453             chptr->banlist->flags |= CHFL_BURST_BAN;
454           }
455           if (ret != -1)
456             /* A new ban was added or an existing one needs to be passed on.
457              * Also add it to sendbuf: */
458             add_token_to_sendbuf(ban, &sblen, &first, &send_it, '%', 0);
459         }
460         break;                  /* Done bans part */
461       }
462       default:                  /* nicks */
463       {
464         char *pv, *p = 0, *nick, *ptr;
465         int first = 1;
466         /* Default mode: */
467         int default_mode = CHFL_DEOPPED;
468         /* Run over all nicks */
469         for (pv = parv[n]; (nick = ircd_strtok(&p, pv, ",")); pv = 0)
470         {
471           struct Client *acptr;
472           if ((ptr = strchr(nick, ':')))        /* New default mode ? */
473           {
474             *ptr = '\0';        /* Fix 'nick' */
475             acptr = findNUser(nick);
476             if (!netride)
477             {
478               /* Calculate new mode change: */
479               default_mode = CHFL_DEOPPED;
480               while (*(++ptr))
481                 if (*ptr == 'o')
482                 {
483                   default_mode |= CHFL_CHANOP;
484                   default_mode &= ~CHFL_DEOPPED;
485                 }
486                 else if (*ptr == 'v')
487                   default_mode |= CHFL_VOICE;
488                 else
489                   break;
490             }
491           }
492           else
493             acptr = findNUser(nick);
494           /*
495            * Note that at this point we already received a 'NICK' for any
496            * <nick> numeric that is joining (and possibly opped) here.
497            * Therefore we consider the following situations:
498            * - The <nick> numeric exists and is from the direction of cptr: ok
499            * - The <nick> numeric does not exist:
500            *   Apparently this previous <nick> numeric was killed (upstream)
501            *   or it collided with an existing <nick> name.
502            * - The <nick> numeric exists but is from another direction:
503            *   Apparently this previous <nick> numeric was killed,
504            *   and due to a reroute it signed on via another link (probably
505            *   a nick [numeric] collision).
506            * Note that it can't be a QUIT or SQUIT, because a QUIT would
507            * come from the same direction as the BURST (cptr) while an
508            * upstream SQUIT removes the source (server) and we would thus
509            * have this BURST ignored already.
510            * This means that if we find the nick and it is from the correct
511            * direction, it joins. If it doesn't exist or is from another
512            * direction, we have to ignore it. If all nicks are ignored, we
513            * remove the channel again when it is empty and don't propagate
514            * the BURST message.
515            */
516           if (acptr && acptr->from == cptr)
517           {
518             /*
519              * The following should do the following:
520              * - Add it to sendbuf for later use.
521              * - If sendbuf is full, send it, and prepare a new
522              *   message in sendbuf.
523              */
524             add_token_to_sendbuf(nick, &sblen, &first, &send_it, 0,
525                 default_mode);
526             /* Let is take effect: (Note that in the case of a netride
527              * 'default_mode' is always CHFL_DEOPPED here). */
528             add_user_to_channel(chptr, acptr, default_mode | CHFL_BURST_JOINED);
529           }
530         }                       /* <-- Next nick */
531         if (!chptr->members)    /* All nicks collided and channel is empty ? */
532         {
533           sub1_from_channel(chptr);
534           return 0;             /* Forget about the (rest of the) message... */
535         }
536         break;                  /* Done nicks part */
537       }
538     }                           /* <-- Next parameter if any */
539   if (!chptr->members)          /* This message only contained bans (then the previous
540                                    message only contained collided nicks, see above) */
541   {
542     sub1_from_channel(chptr);
543     if (!add_banid_not_called)
544       while (next_removed_overlapped_ban());
545     return 0;                   /* Forget about the (rest of the) message... */
546   }
547
548   /* The last (possibly only) message is always send here */
549   if (send_it)                  /* Anything (left) to send ? */
550   {
551     struct DLink *lp;
552     struct Membership* member;
553
554     /* send 'sendbuf' to all downlinks */
555     for (lp = me.serv->down; lp; lp = lp->next)
556     {
557       if (lp->value.cptr == cptr)
558         continue;
559       if (Protocol(lp->value.cptr) > 9)
560         sendbufto_one(lp->value.cptr);
561     }
562
563     /*
564      * Now we finally can screw sendbuf again...
565      * Send all changes to the local clients:
566      *
567      * First send all joins and op them, because 2.9 servers
568      * would protest with a HACK if we first de-opped people.
569      * However, we don't send the +b bans yes, because we
570      * DO first want to -b the old bans (otherwise it's confusing).
571      */
572
573     /* Send all joins: */
574     for (member = chptr->members; member; member = member->next_member)
575       if (IsBurstJoined(member))
576       {
577         sendto_channel_butserv(chptr, member->user, ":%s JOIN :%s",
578                                member->user->name, chptr->chname);
579       }
580
581     if (!netride)
582     {
583       /* Send all +o and +v modes: */
584       for (member = chptr->members; member; member = member->next_member)
585       {
586         if (IsBurstJoined(member))
587         {
588           int mode = CHFL_CHANOP;
589           for (;;)
590           {
591             if ((member->status & mode))
592             {
593               modebuf[mblen2++] = (mode == CHFL_CHANOP) ? 'o' : 'v';
594               parabuf[pblen2++] = ' ';
595               strcpy(parabuf + pblen2, member->user->name);
596               pblen2 += strlen(member->user->name);
597               if (6 == ++cnt)
598               {
599                 modebuf[mblen2] = 0;
600                 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
601                     parv[0], chptr->chname, modebuf, parabuf);
602                 *parabuf = 0;
603                 pblen2 = 0;
604                 mblen2 = 1;
605                 cnt = 0;
606               }
607             }
608             if (mode == CHFL_CHANOP)
609               mode = CHFL_VOICE;
610             else
611               break;
612           }
613         }
614       }
615       /* Flush MODEs: */
616       if (cnt > 0 || mblen2 > 1)
617       {
618         modebuf[mblen2] = 0;
619         sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
620             parv[0], chptr->chname, modebuf, parabuf);
621       }
622     }
623   }
624
625   if (wipeout)
626   {
627     struct Membership* member;
628     struct SLink**     ban;
629     int                mode;
630     char               m;
631     int                count = -1;
632
633     /* Now cancel all previous simple modes */
634     if ((prev_mode & MODE_SECRET))
635       cancel_mode(sptr, chptr, 's', 0, &count);
636     if ((prev_mode & MODE_PRIVATE))
637       cancel_mode(sptr, chptr, 'p', 0, &count);
638     if ((prev_mode & MODE_MODERATED))
639       cancel_mode(sptr, chptr, 'm', 0, &count);
640     if ((prev_mode & MODE_TOPICLIMIT))
641       cancel_mode(sptr, chptr, 't', 0, &count);
642     if ((prev_mode & MODE_INVITEONLY))
643       cancel_mode(sptr, chptr, 'i', 0, &count);
644     if ((prev_mode & MODE_NOPRIVMSGS))
645       cancel_mode(sptr, chptr, 'n', 0, &count);
646     if ((prev_mode & MODE_LIMIT))
647     {
648       current_mode->limit = 0;
649       cancel_mode(sptr, chptr, 'l', 0, &count);
650     }
651     if ((prev_mode & MODE_KEY))
652     {
653       *current_mode->key = 0;
654       cancel_mode(sptr, chptr, 'k', prev_key, &count);
655     }
656     current_mode->mode &= ~prev_mode;
657
658     /* And deop and devoice all net.riders on my side */
659     mode = CHFL_CHANOP;
660     m = 'o';
661     for (;;)
662     {
663       struct Membership* member_next = 0;
664
665       for (member = chptr->members; member; member = member_next)
666       {
667         member_next = member->next_member;
668         if (IsBurstJoined(member))
669           continue;             /* This is not a net.rider from
670                                    this side of the net.junction */
671 #if defined(NO_INVITE_NETRIDE)
672         /*
673          * Kick net riding users from invite only channels.
674          *  - Isomer 25-11-1999
675          */
676         if (chptr->mode.mode & MODE_INVITEONLY) {
677           /* kick is magical - lotsa zombies and other undead.
678            * I'm hoping this is the right idea, comments anyone?
679            * Set everyone to a zombie, remove ops, and then send kicks
680            * everywhere...
681            */
682            if (IsZombie(member)) { /* don't kick ppl twice */
683                 member->status = member->status & ~mode;
684                 continue;
685            }
686
687            sendto_highprot_butone(0, 10, "%s " TOK_KICK " %s %s%s :Net Rider",
688             NumServ(&me), chptr->chname, NumNick(member->user));
689            sendto_channel_butserv(chptr, sptr,
690             ":%s KICK %s %s :Net Rider", me.name, chptr->chname,
691             member->user->name);
692
693            if (MyUser(member->user)) {
694              sendto_lowprot_butone(0, 9, ":%s PART %s",
695                member->user->name, chptr->chname, member->user->name);
696              sendto_highprot_butone(0, 10, "%s%s PART %s",
697                NumNick(member->user), chptr->chname);
698              remove_user_from_channel(member->user, chptr);
699            }
700            else {
701              member->status = (member->status & ~mode) | CHFL_ZOMBIE;
702            }
703            continue;
704         }
705 #endif /* defined(NO_INVITE_NETRIDE) */
706         if ((member->status & mode))
707         {
708           member->status &= ~mode;
709           if (mode == CHFL_CHANOP)
710             SetDeopped(member);
711           cancel_mode(sptr, chptr, m, member->user->name, &count);
712         }
713       }
714       if (mode == CHFL_VOICE)
715         break;
716       mode = CHFL_VOICE;
717       m = 'v';
718     }
719
720     /* And finally wipeout all bans that are left */
721     for (ban = &chptr->banlist; *ban; ) {
722       struct SLink* tmp = *ban;
723       if ((tmp->flags & CHFL_BURST_BAN_WIPEOUT)) {
724         struct Membership* member_z;
725
726         *ban = tmp->next;
727         cancel_mode(sptr, chptr, 'b', tmp->value.ban.banstr, &count);
728
729         /* Copied from del_banid(): */
730         MyFree(tmp->value.ban.banstr);
731         MyFree(tmp->value.ban.who);
732         free_link(tmp);
733
734         /* Erase ban-valid-bit, for channel members that are banned */
735         for (member_z = chptr->members; member_z; member_z = member_z->next_member)
736           if ((member_z->status & CHFL_BANVALIDMASK) == CHFL_BANVALIDMASK)
737             ClearBanValid(member_z);
738       }
739       else
740         ban = &tmp->next;
741     }
742     /* Also wipeout overlapped bans */
743     if (!add_banid_not_called)
744     {
745       struct SLink *ban;
746       while ((ban = next_removed_overlapped_ban()))
747         cancel_mode(sptr, chptr, 'b', ban->value.ban.banstr, &count);
748     }
749     cancel_mode(sptr, chptr, 0, 0, &count);  /* flush */
750   }
751
752   if (send_it && !netride)
753   {
754     struct SLink *bl;
755     int deban;
756
757     if (add_banid_not_called || !(bl = next_removed_overlapped_ban()))
758     {
759       deban = 0;
760       bl = chptr->banlist;
761       *modebuf = '+';
762     }
763     else
764     {
765       deban = 1;
766       *modebuf = '-';
767     }
768
769     mblen2 = 1;
770     pblen2 = 0;
771     cnt = 0;
772     for (;;)
773     {
774       size_t nblen = 0;
775       if (bl)
776         nblen = strlen(bl->value.ban.banstr);
777       if (cnt == 6 || (!bl && cnt) || pblen2 + nblen + 12 > MODEBUFLEN) /* The last check is to make sure
778                                                                            that the receiving 2.9 will
779                                                                            still process this */
780       {
781         /* Time to send buffer */
782         modebuf[mblen2] = 0;
783         sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
784             parv[0], chptr->chname, modebuf, parabuf);
785         *modebuf = deban ? '-' : '+';
786         mblen2 = 1;
787         pblen2 = 0;
788         cnt = 0;
789       }
790       if (!bl)                  /* Done ? */
791         break;
792       if (deban || (bl->flags & CHFL_BURST_BAN))
793       {
794         /* Add ban to buffers and remove it */
795         modebuf[mblen2++] = 'b';
796         parabuf[pblen2++] = ' ';
797         strcpy(parabuf + pblen2, bl->value.ban.banstr);
798         pblen2 += nblen;
799         cnt++;
800         bl->flags &= ~CHFL_BURST_BAN;
801       }
802       if (deban)
803       {
804         if (!(bl = next_removed_overlapped_ban()))
805         {
806           deban = 0;
807           modebuf[mblen2++] = '+';
808           bl = chptr->banlist;
809         }
810       }
811       else
812         bl = bl->next;
813     }
814     /* Flush MODE [-b]+b ...: */
815     if (cnt > 0 || mblen2 > 1)
816     {
817       modebuf[mblen2] = 0;
818       sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
819           parv[0], chptr->chname, modebuf, parabuf);
820     }
821   }
822   return 0;
823 }
824
825
826 #if 0
827 /*
828  * m_burst  --  by Run carlo@runaway.xs4all.nl  december 1995 till march 1997
829  *
830  * parv[0] = sender prefix
831  * parv[1] = channel name
832  * parv[2] = channel timestamp
833  * The meaning of the following parv[]'s depend on their first character:
834  * If parv[n] starts with a '+':
835  * Net burst, additive modes
836  *   parv[n] = <mode>
837  *   parv[n+1] = <param> (optional)
838  *   parv[n+2] = <param> (optional)
839  * If parv[n] starts with a '%', then n will be parc-1:
840  *   parv[n] = %<ban> <ban> <ban> ...
841  * If parv[n] starts with another character:
842  *   parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
843  *   where <mode> is the channel mode (ov) of nick and all following nicks.
844  *
845  * Example:
846  * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
847  *
848  * Anti net.ride code.
849  *
850  * When the channel already exist, and its TS is larger then
851  * the TS in the BURST message, then we cancel all existing modes.
852  * If its is smaller then the received BURST message is ignored.
853  * If it's equal, then the received modes are just added.
854  */
855 int m_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
856 {
857   struct Channel* chptr;
858   time_t          timestamp;
859   int             netride = 0;
860   int             wipeout = 0;
861   int             n;
862   int             send_it = 0;
863   int             add_banid_not_called = 1;
864   struct Mode*    current_mode;
865   size_t          sblen;
866   size_t          mblen = 0;
867   int             mblen2;
868   int             pblen2;
869   int             cnt;
870   int             prev_mode;
871   char            prev_key[KEYLEN + 1];
872   struct Membership* member;
873   struct SLink*   lp;
874   char modebuf[MODEBUFLEN];
875   char parabuf[MODEBUFLEN];
876   char bmodebuf[MODEBUFLEN];
877   char bparambuf[MODEBUFLEN];
878
879   /* BURST is only for servers and has at least 4 parameters */
880   if (!IsServer(cptr) || parc < 4)
881     return 0;
882
883   if (!IsBurst(sptr))
884   {
885     int i;
886     char *p;
887     if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD))
888     {
889       p =
890           sprintf_irc(sendbuf,
891           ":%s NOTICE * :*** Notice -- HACK(4): %s BURST %s %s", me.name,
892           sptr->name, parv[1], parv[2]);
893       for (i = 3; i < parc - 1; ++i)
894         p = sprintf_irc(p, " %s", parv[i]);
895       sprintf_irc(p, " :%s", parv[parc - 1]);
896       sendbufto_op_mask(SNO_HACK4);
897     }
898     else
899     {
900 #if 1                           /* FIXME: This should be removed after all HUBs upgraded to ircu2.10.05 */
901       SetBurst(sptr);
902       if (MyConnect(sptr))
903 #endif
904         return exit_client_msg(cptr, cptr, &me,
905             "HACK: BURST message outside net.burst from %s", sptr->name);
906     }
907   }
908
909   /* Find the channel, or create it - note that the creation time
910    * will be 0 if it has to be created */
911   chptr = get_channel(sptr, parv[1], CGT_CREATE);
912   current_mode = &chptr->mode;
913   prev_mode = chptr->mode.mode;
914   if (*chptr->mode.key)
915   {
916     prev_mode |= MODE_KEY;
917     strcpy(prev_key, chptr->mode.key);
918   }
919   if (chptr->mode.limit)
920     prev_mode |= MODE_LIMIT;
921
922   timestamp = atoi(parv[2]);
923
924   /* Copy the new TS when the received creationtime appears to be older */
925   if (!chptr->creationtime || chptr->creationtime > timestamp)
926   {
927     /* Set the new timestamp */
928     chptr->creationtime = timestamp;
929     send_it = 1;                /* Make sure we pass on the different timestamp ! */
930     /* Mark all bans as needed to be wiped out */
931     for (lp = chptr->banlist; lp; lp = lp->next)
932       lp->flags |= CHFL_BURST_BAN_WIPEOUT;
933     /*
934      * Only the first BURST for this channel can have creationtime > timestamp,
935      * so at this moment ALL members are on OUR side, and thus all net.riders:
936      */
937     wipeout = 1;
938   }
939   for (member = chptr->members; member; member = member->next_member)
940     member->status &= ~CHFL_BURST_JOINED;    /* Set later for nicks in the BURST msg */
941   /* If `wipeout' is set then these will be deopped later. */
942
943   /* If the entering creationtime is younger, ignore the modes */
944   if (chptr->creationtime < timestamp)
945     netride = 1;                /* Only pass on the nicks (so they JOIN) */
946
947   /* Prepare buffers to pass the message */
948   *bparambuf = *bmodebuf = *parabuf = '\0';
949   pblen2 = 0;
950   *modebuf = '+';
951   mblen2 = 1;
952   cnt = 0;
953   sblen = sprintf_irc(sendbuf, "%s B %s " TIME_T_FMT,
954       NumServ(sptr), chptr->chname, chptr->creationtime) - sendbuf;
955
956   /* Run over all remaining parameters */
957   for (n = 3; n < parc; n++)
958     switch (*parv[n])           /* What type is it ? mode, nicks or bans ? */
959     {
960       case '+':         /* modes */
961       {
962         char *p = parv[n];
963         while (*(++p))          /* Run over all mode characters */
964         {
965           switch (*p)           /* which mode ? */
966           {
967               /*
968                * The following cases all do the following:
969                * - In case wipeout needed, reset 'prev_mode' to indicate this
970                *   mode should not be cancelled.
971                * - If wipeout or (not netride and the new mode is a change),
972                *   add it to bmodebuf and bparabuf for propagation.
973                * - Else ignore it.
974                * - Add it to modebuf and parabuf for propagation to the
975                *   clients when not netride and the new mode is a change.
976                * Special cases:
977                * - If a +s is received, cancel a +p and sent a -p to the
978                *   clients too (if +p was set).
979                * - If a +p is received and +s is set, ignore the +p.
980                */
981             case 'i':
982             {
983               int tmp;
984               prev_mode &= ~MODE_INVITEONLY;
985               if (!(tmp = netride ||
986                   (current_mode->mode & MODE_INVITEONLY)) || wipeout)
987               {
988                 bmodebuf[mblen++] = 'i';
989                 current_mode->mode |= MODE_INVITEONLY;
990               }
991               if (!tmp)
992                 modebuf[mblen2++] = 'i';
993               break;
994             }
995             case 'k':
996             {
997               int tmp;
998               char *param = parv[++n];
999               prev_mode &= ~MODE_KEY;
1000               if (!(tmp = netride || (*current_mode->key &&
1001                   (!strcmp(current_mode->key, param) ||
1002                   (!wipeout && strcmp(current_mode->key, param) < 0)))) ||
1003                   wipeout)
1004               {
1005                 bmodebuf[mblen++] = 'k';
1006                 strcat(bparambuf, " ");
1007                 strcat(bparambuf, param);
1008                 ircd_strncpy(current_mode->key, param, KEYLEN);
1009               }
1010               if (!tmp && !wipeout)
1011               {
1012                 modebuf[mblen2++] = 'k';
1013                 parabuf[pblen2++] = ' ';
1014                 strcpy(parabuf + pblen2, param);
1015                 pblen2 += strlen(param);
1016                 cnt++;
1017               }
1018               break;
1019             }
1020             case 'l':
1021             {
1022               int tmp;
1023               unsigned int param = atoi(parv[++n]);
1024               prev_mode &= ~MODE_LIMIT;
1025               if (!(tmp = netride || (current_mode->limit &&
1026                   (current_mode->limit == param ||
1027                   (!wipeout && current_mode->limit < param)))) || wipeout)
1028               {
1029                 bmodebuf[mblen++] = 'l';
1030                 sprintf_irc(bparambuf + strlen(bparambuf), " %d", param);
1031                 current_mode->limit = param;
1032               }
1033               if (!tmp)
1034               {
1035                 modebuf[mblen2++] = 'l';
1036                 pblen2 = sprintf_irc(parabuf + pblen2, " %d", param) - parabuf;
1037                 cnt++;
1038               }
1039               break;
1040             }
1041             case 'm':
1042             {
1043               int tmp;
1044               prev_mode &= ~MODE_MODERATED;
1045               if (!(tmp = netride ||
1046                   (current_mode->mode & MODE_MODERATED)) || wipeout)
1047               {
1048                 bmodebuf[mblen++] = 'm';
1049                 current_mode->mode |= MODE_MODERATED;
1050               }
1051               if (!tmp)
1052                 modebuf[mblen2++] = 'm';
1053               break;
1054             }
1055             case 'n':
1056             {
1057               int tmp;
1058               prev_mode &= ~MODE_NOPRIVMSGS;
1059               if (!(tmp = netride ||
1060                   (current_mode->mode & MODE_NOPRIVMSGS)) || wipeout)
1061               {
1062                 bmodebuf[mblen++] = 'n';
1063                 current_mode->mode |= MODE_NOPRIVMSGS;
1064               }
1065               if (!tmp)
1066                 modebuf[mblen2++] = 'n';
1067               break;
1068             }
1069             case 'p':
1070             {
1071               int tmp;
1072
1073               /* Special case: */
1074               if (!netride && !wipeout && (current_mode->mode & MODE_SECRET))
1075                 break;
1076
1077               prev_mode &= ~MODE_PRIVATE;
1078               if (!(tmp = netride ||
1079                   (current_mode->mode & MODE_PRIVATE)) || wipeout)
1080               {
1081                 bmodebuf[mblen++] = 'p';
1082                 current_mode->mode |= MODE_PRIVATE;
1083               }
1084               if (!tmp)
1085                 modebuf[mblen2++] = 'p';
1086               break;
1087             }
1088             case 's':
1089             {
1090               int tmp;
1091               prev_mode &= ~MODE_SECRET;
1092               if (!(tmp = netride ||
1093                   (current_mode->mode & MODE_SECRET)) || wipeout)
1094               {
1095                 bmodebuf[mblen++] = 's';
1096                 current_mode->mode |= MODE_SECRET;
1097               }
1098               if (!tmp)
1099                 modebuf[mblen2++] = 's';
1100
1101               /* Special case: */
1102               if (!netride && !wipeout && (current_mode->mode & MODE_PRIVATE))
1103               {
1104                 int i;
1105                 for (i = mblen2 - 1; i >= 0; --i)
1106                   modebuf[i + 2] = modebuf[i];
1107                 modebuf[0] = '-';
1108                 modebuf[1] = 'p';
1109                 mblen2 += 2;
1110                 current_mode->mode &= ~MODE_PRIVATE;
1111               }
1112
1113               break;
1114             }
1115             case 't':
1116             {
1117               int tmp;
1118               prev_mode &= ~MODE_TOPICLIMIT;
1119               if (!(tmp = netride ||
1120                   (current_mode->mode & MODE_TOPICLIMIT)) || wipeout)
1121               {
1122                 bmodebuf[mblen++] = 't';
1123                 current_mode->mode |= MODE_TOPICLIMIT;
1124               }
1125               if (!tmp)
1126                 modebuf[mblen2++] = 't';
1127               break;
1128             }
1129           }
1130         }                       /* <-- while over all modes */
1131
1132         bmodebuf[mblen] = '\0';
1133         sendbuf[sblen] = '\0';
1134         if (mblen)              /* Anything to send at all ? */
1135         {
1136           send_it = 1;
1137           strcpy(sendbuf + sblen, " +");
1138           sblen += 2;
1139           strcpy(sendbuf + sblen, bmodebuf);
1140           sblen += mblen;
1141           strcpy(sendbuf + sblen, bparambuf);
1142           sblen += strlen(bparambuf);
1143         }
1144         break;                  /* Done mode part */
1145       }
1146       case '%':         /* bans */
1147       {
1148         char *pv, *p = 0, *ban;
1149         int first = 1;
1150         if (netride)
1151           break;                /* Ignore bans */
1152         /* Run over all bans */
1153         for (pv = parv[n] + 1; (ban = ircd_strtok(&p, pv, " ")); pv = 0)
1154         {
1155           int ret;
1156           /*
1157            * The following part should do the following:
1158            * - If the new (un)ban is not a _change_ it is ignored.
1159            * - Else, add it to sendbuf for later use.
1160            * - If sendbuf is full, send it, and prepare a new
1161            *   message in sendbuf.
1162            */
1163           ret = add_banid(sptr, chptr, ban, 1, add_banid_not_called);
1164           if (ret == 0)
1165           {
1166             add_banid_not_called = 0;
1167             /* Mark this new ban so we can send it to the clients later */
1168             chptr->banlist->flags |= CHFL_BURST_BAN;
1169           }
1170           if (ret != -1)
1171             /* A new ban was added or an existing one needs to be passed on.
1172              * Also add it to sendbuf: */
1173             add_token_to_sendbuf(ban, &sblen, &first, &send_it, '%', 0);
1174         }
1175         break;                  /* Done bans part */
1176       }
1177       default:                  /* nicks */
1178       {
1179         char *pv, *p = 0, *nick, *ptr;
1180         int first = 1;
1181         /* Default mode: */
1182         int default_mode = CHFL_DEOPPED;
1183         /* Run over all nicks */
1184         for (pv = parv[n]; (nick = ircd_strtok(&p, pv, ",")); pv = 0)
1185         {
1186           struct Client *acptr;
1187           if ((ptr = strchr(nick, ':')))        /* New default mode ? */
1188           {
1189             *ptr = '\0';        /* Fix 'nick' */
1190             acptr = findNUser(nick);
1191             if (!netride)
1192             {
1193               /* Calculate new mode change: */
1194               default_mode = CHFL_DEOPPED;
1195               while (*(++ptr))
1196                 if (*ptr == 'o')
1197                 {
1198                   default_mode |= CHFL_CHANOP;
1199                   default_mode &= ~CHFL_DEOPPED;
1200                 }
1201                 else if (*ptr == 'v')
1202                   default_mode |= CHFL_VOICE;
1203                 else
1204                   break;
1205             }
1206           }
1207           else
1208             acptr = findNUser(nick);
1209           /*
1210            * Note that at this point we already received a 'NICK' for any
1211            * <nick> numeric that is joining (and possibly opped) here.
1212            * Therefore we consider the following situations:
1213            * - The <nick> numeric exists and is from the direction of cptr: ok
1214            * - The <nick> numeric does not exist:
1215            *   Apparently this previous <nick> numeric was killed (upstream)
1216            *   or it collided with an existing <nick> name.
1217            * - The <nick> numeric exists but is from another direction:
1218            *   Apparently this previous <nick> numeric was killed,
1219            *   and due to a reroute it signed on via another link (probably
1220            *   a nick [numeric] collision).
1221            * Note that it can't be a QUIT or SQUIT, because a QUIT would
1222            * come from the same direction as the BURST (cptr) while an
1223            * upstream SQUIT removes the source (server) and we would thus
1224            * have this BURST ignored already.
1225            * This means that if we find the nick and it is from the correct
1226            * direction, it joins. If it doesn't exist or is from another
1227            * direction, we have to ignore it. If all nicks are ignored, we
1228            * remove the channel again when it is empty and don't propagate
1229            * the BURST message.
1230            */
1231           if (acptr && acptr->from == cptr)
1232           {
1233             /*
1234              * The following should do the following:
1235              * - Add it to sendbuf for later use.
1236              * - If sendbuf is full, send it, and prepare a new
1237              *   message in sendbuf.
1238              */
1239             add_token_to_sendbuf(nick, &sblen, &first, &send_it, 0,
1240                 default_mode);
1241             /* Let is take effect: (Note that in the case of a netride
1242              * 'default_mode' is always CHFL_DEOPPED here). */
1243             add_user_to_channel(chptr, acptr, default_mode | CHFL_BURST_JOINED);
1244           }
1245         }                       /* <-- Next nick */
1246         if (!chptr->members)    /* All nicks collided and channel is empty ? */
1247         {
1248           sub1_from_channel(chptr);
1249           return 0;             /* Forget about the (rest of the) message... */
1250         }
1251         break;                  /* Done nicks part */
1252       }
1253     }                           /* <-- Next parameter if any */
1254   if (!chptr->members)          /* This message only contained bans (then the previous
1255                                    message only contained collided nicks, see above) */
1256   {
1257     sub1_from_channel(chptr);
1258     if (!add_banid_not_called)
1259       while (next_removed_overlapped_ban());
1260     return 0;                   /* Forget about the (rest of the) message... */
1261   }
1262
1263   /* The last (possibly only) message is always send here */
1264   if (send_it)                  /* Anything (left) to send ? */
1265   {
1266     struct DLink *lp;
1267     struct Membership* member;
1268
1269     /* send 'sendbuf' to all downlinks */
1270     for (lp = me.serv->down; lp; lp = lp->next)
1271     {
1272       if (lp->value.cptr == cptr)
1273         continue;
1274       if (Protocol(lp->value.cptr) > 9)
1275         sendbufto_one(lp->value.cptr);
1276     }
1277
1278     /*
1279      * Now we finally can screw sendbuf again...
1280      * Send all changes to the local clients:
1281      *
1282      * First send all joins and op them, because 2.9 servers
1283      * would protest with a HACK if we first de-opped people.
1284      * However, we don't send the +b bans yes, because we
1285      * DO first want to -b the old bans (otherwise it's confusing).
1286      */
1287
1288     /* Send all joins: */
1289     for (member = chptr->members; member; member = member->next_member)
1290       if (IsBurstJoined(member))
1291       {
1292         sendto_channel_butserv(chptr, member->user, ":%s JOIN :%s",
1293                                member->user->name, chptr->chname);
1294       }
1295
1296     if (!netride)
1297     {
1298       /* Send all +o and +v modes: */
1299       for (member = chptr->members; member; member = member->next_member)
1300       {
1301         if (IsBurstJoined(member))
1302         {
1303           int mode = CHFL_CHANOP;
1304           for (;;)
1305           {
1306             if ((member->status & mode))
1307             {
1308               modebuf[mblen2++] = (mode == CHFL_CHANOP) ? 'o' : 'v';
1309               parabuf[pblen2++] = ' ';
1310               strcpy(parabuf + pblen2, member->user->name);
1311               pblen2 += strlen(member->user->name);
1312               if (6 == ++cnt)
1313               {
1314                 modebuf[mblen2] = 0;
1315                 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
1316                     parv[0], chptr->chname, modebuf, parabuf);
1317                 *parabuf = 0;
1318                 pblen2 = 0;
1319                 mblen2 = 1;
1320                 cnt = 0;
1321               }
1322             }
1323             if (mode == CHFL_CHANOP)
1324               mode = CHFL_VOICE;
1325             else
1326               break;
1327           }
1328         }
1329       }
1330       /* Flush MODEs: */
1331       if (cnt > 0 || mblen2 > 1)
1332       {
1333         modebuf[mblen2] = 0;
1334         sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
1335             parv[0], chptr->chname, modebuf, parabuf);
1336       }
1337     }
1338   }
1339
1340   if (wipeout)
1341   {
1342     struct Membership* member;
1343     struct SLink**     ban;
1344     int                mode;
1345     char               m;
1346     int                count = -1;
1347
1348     /* Now cancel all previous simple modes */
1349     if ((prev_mode & MODE_SECRET))
1350       cancel_mode(sptr, chptr, 's', 0, &count);
1351     if ((prev_mode & MODE_PRIVATE))
1352       cancel_mode(sptr, chptr, 'p', 0, &count);
1353     if ((prev_mode & MODE_MODERATED))
1354       cancel_mode(sptr, chptr, 'm', 0, &count);
1355     if ((prev_mode & MODE_TOPICLIMIT))
1356       cancel_mode(sptr, chptr, 't', 0, &count);
1357     if ((prev_mode & MODE_INVITEONLY))
1358       cancel_mode(sptr, chptr, 'i', 0, &count);
1359     if ((prev_mode & MODE_NOPRIVMSGS))
1360       cancel_mode(sptr, chptr, 'n', 0, &count);
1361     if ((prev_mode & MODE_LIMIT))
1362     {
1363       current_mode->limit = 0;
1364       cancel_mode(sptr, chptr, 'l', 0, &count);
1365     }
1366     if ((prev_mode & MODE_KEY))
1367     {
1368       *current_mode->key = 0;
1369       cancel_mode(sptr, chptr, 'k', prev_key, &count);
1370     }
1371     current_mode->mode &= ~prev_mode;
1372
1373     /* And deop and devoice all net.riders on my side */
1374     mode = CHFL_CHANOP;
1375     m = 'o';
1376     for (;;)
1377     {
1378       struct Membership* member_next = 0;
1379
1380       for (member = chptr->members; member; member = member_next)
1381       {
1382         member_next = member->next_member;
1383         if (IsBurstJoined(member))
1384           continue;             /* This is not a net.rider from
1385                                    this side of the net.junction */
1386 #if defined(NO_INVITE_NETRIDE)
1387         /*
1388          * Kick net riding users from invite only channels.
1389          *  - Isomer 25-11-1999
1390          */
1391         if (chptr->mode.mode & MODE_INVITEONLY) {
1392           /* kick is magical - lotsa zombies and other undead.
1393            * I'm hoping this is the right idea, comments anyone?
1394            * Set everyone to a zombie, remove ops, and then send kicks
1395            * everywhere...
1396            */
1397            if (IsZombie(member)) { /* don't kick ppl twice */
1398                 member->status = member->status & ~mode;
1399                 continue;
1400            }
1401            member->status = (member->status & ~mode) | CHFL_ZOMBIE;
1402
1403            sendto_highprot_butone(0, 10, "%s " TOK_KICK "%s %s%s :Net Rider",
1404             NumServ(&me), chptr->chname, NumNick(member->user));
1405            sendto_channel_butserv(chptr, sptr,
1406             ":%s KICK %s %s :Net Rider", me.name, chptr->chname,
1407             member->user->name);
1408
1409            if (MyUser(member->user)) {
1410              sendto_lowprot_butone(0, 9, ":%s PART %s",
1411                member->user->name, chptr->chname, member->user->name);
1412              sendto_highprot_butone(0, 10, "%s%s PART %s",
1413                NumNick(member->user), chptr->chname);
1414              remove_user_from_channel(member->user, chptr);
1415            }
1416            else {
1417              member->status = (member->status & ~mode) | CHFL_ZOMBIE;
1418            }
1419            continue;
1420         }
1421 #endif /* defined(NO_INVITE_NETRIDE) */
1422         if ((member->status & mode))
1423         {
1424           member->status &= ~mode;
1425           if (mode == CHFL_CHANOP)
1426             SetDeopped(member);
1427           cancel_mode(sptr, chptr, m, member->user->name, &count);
1428         }
1429       }
1430       if (mode == CHFL_VOICE)
1431         break;
1432       mode = CHFL_VOICE;
1433       m = 'v';
1434     }
1435
1436     /* And finally wipeout all bans that are left */
1437     for (ban = &chptr->banlist; *ban; ) {
1438       struct SLink* tmp = *ban;
1439       if ((tmp->flags & CHFL_BURST_BAN_WIPEOUT)) {
1440         struct Membership* member_z;
1441
1442         *ban = tmp->next;
1443         cancel_mode(sptr, chptr, 'b', tmp->value.ban.banstr, &count);
1444
1445         /* Copied from del_banid(): */
1446         MyFree(tmp->value.ban.banstr);
1447         MyFree(tmp->value.ban.who);
1448         free_link(tmp);
1449
1450         /* Erase ban-valid-bit, for channel members that are banned */
1451         for (member_z = chptr->members; member_z; member_z = member_z->next_member)
1452           if ((member_z->status & CHFL_BANVALIDMASK) == CHFL_BANVALIDMASK)
1453             ClearBanValid(member_z);
1454       }
1455       else
1456         ban = &tmp->next;
1457     }
1458     /* Also wipeout overlapped bans */
1459     if (!add_banid_not_called)
1460     {
1461       struct SLink *ban;
1462       while ((ban = next_removed_overlapped_ban()))
1463         cancel_mode(sptr, chptr, 'b', ban->value.ban.banstr, &count);
1464     }
1465     cancel_mode(sptr, chptr, 0, 0, &count);  /* flush */
1466   }
1467
1468   if (send_it && !netride)
1469   {
1470     struct SLink *bl;
1471     int deban;
1472
1473     if (add_banid_not_called || !(bl = next_removed_overlapped_ban()))
1474     {
1475       deban = 0;
1476       bl = chptr->banlist;
1477       *modebuf = '+';
1478     }
1479     else
1480     {
1481       deban = 1;
1482       *modebuf = '-';
1483     }
1484
1485     mblen2 = 1;
1486     pblen2 = 0;
1487     cnt = 0;
1488     for (;;)
1489     {
1490       size_t nblen = 0;
1491       if (bl)
1492         nblen = strlen(bl->value.ban.banstr);
1493       if (cnt == 6 || (!bl && cnt) || pblen2 + nblen + 12 > MODEBUFLEN) /* The last check is to make sure
1494                                                                            that the receiving 2.9 will
1495                                                                            still process this */
1496       {
1497         /* Time to send buffer */
1498         modebuf[mblen2] = 0;
1499         sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
1500             parv[0], chptr->chname, modebuf, parabuf);
1501         *modebuf = deban ? '-' : '+';
1502         mblen2 = 1;
1503         pblen2 = 0;
1504         cnt = 0;
1505       }
1506       if (!bl)                  /* Done ? */
1507         break;
1508       if (deban || (bl->flags & CHFL_BURST_BAN))
1509       {
1510         /* Add ban to buffers and remove it */
1511         modebuf[mblen2++] = 'b';
1512         parabuf[pblen2++] = ' ';
1513         strcpy(parabuf + pblen2, bl->value.ban.banstr);
1514         pblen2 += nblen;
1515         cnt++;
1516         bl->flags &= ~CHFL_BURST_BAN;
1517       }
1518       if (deban)
1519       {
1520         if (!(bl = next_removed_overlapped_ban()))
1521         {
1522           deban = 0;
1523           modebuf[mblen2++] = '+';
1524           bl = chptr->banlist;
1525         }
1526       }
1527       else
1528         bl = bl->next;
1529     }
1530     /* Flush MODE [-b]+b ...: */
1531     if (cnt > 0 || mblen2 > 1)
1532     {
1533       modebuf[mblen2] = 0;
1534       sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
1535           parv[0], chptr->chname, modebuf, parabuf);
1536     }
1537   }
1538
1539   return 0;
1540 }
1541 #endif /* 0 */
1542