Author: David M <captjay@superlink.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                         me.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
1991 #ifdef OPER_WALK_THROUGH_LMODES
1992   if (IsOperOnLocalChannel(sptr, chptr->chname))
1993     return 0;
1994 #endif
1995   /*
1996    * Now a banned user CAN join if invited -- Nemesi
1997    * Now a user CAN escape channel limit if invited -- bfriendly
1998    */
1999   if ((chptr->mode.mode & MODE_INVITEONLY) || (is_banned(sptr, chptr, NULL)
2000       || (chptr->mode.limit && chptr->users >= chptr->mode.limit)))
2001   {
2002     for (lp = sptr->user->invited; lp; lp = lp->next)
2003       if (lp->value.chptr == chptr)
2004         break;
2005     if (!lp)
2006     {
2007       if (chptr->mode.limit && chptr->users >= chptr->mode.limit)
2008         return (ERR_CHANNELISFULL);
2009       /*
2010        * This can return an "Invite only" msg instead of the "You are banned"
2011        * if _both_ conditions are true, but who can say what is more
2012        * appropriate ? checking again IsBanned would be _SO_ cpu-xpensive !
2013        */
2014       return ((chptr->mode.mode & MODE_INVITEONLY) ?
2015           ERR_INVITEONLYCHAN : ERR_BANNEDFROMCHAN);
2016     }
2017   }
2018
2019   /* now using compall (above) to test against a whole key ring -Kev */
2020   if (*chptr->mode.key && (BadPtr(key) || compall(chptr->mode.key, key)))
2021     return (ERR_BADCHANNELKEY);
2022
2023   return 0;
2024 }
2025
2026 /*
2027  * Remove bells and commas from channel name
2028  */
2029
2030 static void clean_channelname(char *cn)
2031 {
2032   for (; *cn; cn++)
2033   {
2034     if (!isIrcCh(*cn))
2035     {
2036       *cn = '\0';
2037       return;
2038     }
2039     if (isIrcCl(*cn))
2040 #ifndef FIXME
2041     {
2042 #endif
2043       *cn = toLower(*cn);
2044 #ifndef FIXME
2045       /* Missed the Icelandic letter ETH last time: */
2046       if ((unsigned char)(*cn) == 0xd0)
2047         *cn = (char)0xf0;
2048     }
2049 #endif
2050   }
2051 }
2052
2053 /*
2054  *  Get Channel block for i (and allocate a new channel
2055  *  block, if it didn't exists before).
2056  */
2057 static aChannel *get_channel(aClient *cptr, char *chname, int flag)
2058 {
2059   Reg1 aChannel *chptr;
2060   int len;
2061
2062   if (BadPtr(chname))
2063     return NULL;
2064
2065   len = strlen(chname);
2066   if (MyUser(cptr) && len > CHANNELLEN)
2067   {
2068     len = CHANNELLEN;
2069     *(chname + CHANNELLEN) = '\0';
2070   }
2071   if ((chptr = FindChannel(chname)))
2072     return (chptr);
2073   if (flag == CREATE)
2074   {
2075     chptr = (aChannel *)RunMalloc(sizeof(aChannel) + len);
2076     ++nrof.channels;
2077     memset(chptr, 0, sizeof(aChannel));
2078     strcpy(chptr->chname, chname);
2079     if (channel)
2080       channel->prevch = chptr;
2081     chptr->prevch = NULL;
2082     chptr->nextch = channel;
2083     chptr->creationtime = MyUser(cptr) ? TStime() : (time_t) 0;
2084     channel = chptr;
2085     hAddChannel(chptr);
2086   }
2087   return chptr;
2088 }
2089
2090 static void add_invite(aClient *cptr, aChannel *chptr)
2091 {
2092   Reg1 Link *inv, **tmp;
2093
2094   del_invite(cptr, chptr);
2095   /*
2096    * Delete last link in chain if the list is max length
2097    */
2098   if (list_length(cptr->user->invited) >= MAXCHANNELSPERUSER)
2099     del_invite(cptr, cptr->user->invited->value.chptr);
2100   /*
2101    * Add client to channel invite list
2102    */
2103   inv = make_link();
2104   inv->value.cptr = cptr;
2105   inv->next = chptr->invites;
2106   chptr->invites = inv;
2107   /*
2108    * Add channel to the end of the client invite list
2109    */
2110   for (tmp = &(cptr->user->invited); *tmp; tmp = &((*tmp)->next));
2111   inv = make_link();
2112   inv->value.chptr = chptr;
2113   inv->next = NULL;
2114   (*tmp) = inv;
2115 }
2116
2117 /*
2118  * Delete Invite block from channel invite list and client invite list
2119  */
2120 void del_invite(aClient *cptr, aChannel *chptr)
2121 {
2122   Reg1 Link **inv, *tmp;
2123
2124   for (inv = &(chptr->invites); (tmp = *inv); inv = &tmp->next)
2125     if (tmp->value.cptr == cptr)
2126     {
2127       *inv = tmp->next;
2128       free_link(tmp);
2129       break;
2130     }
2131
2132   for (inv = &(cptr->user->invited); (tmp = *inv); inv = &tmp->next)
2133     if (tmp->value.chptr == chptr)
2134     {
2135       *inv = tmp->next;
2136       free_link(tmp);
2137       break;
2138     }
2139 }
2140
2141 /* List and skip all channels that are listen */
2142 void list_next_channels(aClient *cptr, int nr)
2143 {
2144   aListingArgs *args = cptr->listing;
2145   aChannel *chptr = args->chptr;
2146   chptr->mode.mode &= ~MODE_LISTED;
2147   while (is_listed(chptr) || --nr >= 0)
2148   {
2149     for (; chptr; chptr = chptr->nextch)
2150     {
2151       if (!cptr->user || (SecretChannel(chptr) && !IsMember(cptr, chptr)))
2152         continue;
2153       if (chptr->users > args->min_users && chptr->users < args->max_users &&
2154           chptr->creationtime > args->min_time &&
2155           chptr->creationtime < args->max_time &&
2156           (!args->topic_limits || (*chptr->topic &&
2157           chptr->topic_time > args->min_topic_time &&
2158           chptr->topic_time < args->max_topic_time)))
2159       {
2160         sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name,
2161             ShowChannel(cptr, chptr) ? chptr->chname : "*",
2162             chptr->users, ShowChannel(cptr, chptr) ? chptr->topic : "");
2163         chptr = chptr->nextch;
2164         break;
2165       }
2166     }
2167     if (!chptr)
2168     {
2169       RunFree(cptr->listing);
2170       cptr->listing = NULL;
2171       sendto_one(cptr, rpl_str(RPL_LISTEND), me.name, cptr->name);
2172       break;
2173     }
2174   }
2175   if (chptr)
2176   {
2177     cptr->listing->chptr = chptr;
2178     chptr->mode.mode |= MODE_LISTED;
2179   }
2180 }
2181
2182 /*
2183  *  Subtract one user from channel i (and free channel
2184  *  block, if channel became empty).
2185  */
2186 static void sub1_from_channel(aChannel *chptr)
2187 {
2188   Reg2 Link *tmp;
2189   Link *obtmp;
2190
2191   if (chptr->users > 1)         /* Can be 0, called for an empty channel too */
2192   {
2193     --chptr->users;
2194     return;
2195   }
2196
2197   /* Channel became (or was) empty: Remove channel */
2198   if (is_listed(chptr))
2199   {
2200     int i;
2201     for (i = 0; i <= highest_fd; i++)
2202     {
2203       aClient *acptr;
2204       if ((acptr = loc_clients[i]) && acptr->listing &&
2205           acptr->listing->chptr == chptr)
2206       {
2207         list_next_channels(acptr, 1);
2208         break;                  /* Only one client can list a channel */
2209       }
2210     }
2211   }
2212   /*
2213    * Now, find all invite links from channel structure
2214    */
2215   while ((tmp = chptr->invites))
2216     del_invite(tmp->value.cptr, chptr);
2217
2218   tmp = chptr->banlist;
2219   while (tmp)
2220   {
2221     obtmp = tmp;
2222     tmp = tmp->next;
2223     RunFree(obtmp->value.ban.banstr);
2224     RunFree(obtmp->value.ban.who);
2225     free_link(obtmp);
2226   }
2227   if (chptr->prevch)
2228     chptr->prevch->nextch = chptr->nextch;
2229   else
2230     channel = chptr->nextch;
2231   if (chptr->nextch)
2232     chptr->nextch->prevch = chptr->prevch;
2233   hRemChannel(chptr);
2234   --nrof.channels;
2235   RunFree((char *)chptr);
2236 }
2237
2238 /*
2239  * m_join
2240  *
2241  * parv[0] = sender prefix
2242  * parv[1] = channel
2243  * parv[2] = channel keys (client), or channel TS (server)
2244  */
2245 int m_join(aClient *cptr, aClient *sptr, int parc, char *parv[])
2246 {
2247   static char jbuf[BUFSIZE], mbuf[BUFSIZE];
2248   Reg1 Link *lp;
2249   Reg3 aChannel *chptr;
2250   Reg4 char *name, *keysOrTS = NULL;
2251   int i = 0, zombie = 0, sendcreate = 0;
2252   unsigned int flags = 0;
2253   size_t jlen = 0, mlen = 0;
2254   size_t *buflen;
2255   char *p = NULL, *bufptr;
2256
2257   if (parc < 2 || *parv[1] == '\0')
2258   {
2259     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "JOIN");
2260     return 0;
2261   }
2262
2263   for (p = parv[1]; *p; p++)    /* find the last "JOIN 0" in the line -Kev */
2264     if (*p == '0'
2265         && (*(p + 1) == ',' || *(p + 1) == '\0' || !isIrcCh(*(p + 1))))
2266     {
2267       /* If it's a single "0", remember the place; we will start parsing
2268          the channels after the last 0 in the line -Kev */
2269       parv[1] = p;
2270       if (!*(p + 1))
2271         break;
2272       p++;
2273     }
2274     else
2275     {                           /* Step through to the next comma or until the
2276                                    end of the line, in an attempt to save CPU
2277                                    -Kev */
2278       while (*p != ',' && *p != '\0')
2279         p++;
2280       if (!*p)
2281         break;
2282     }
2283
2284   keysOrTS = parv[2];           /* Remember where our keys are or the TS is;
2285                                    parv[2] needs to be NULL for the call to
2286                                    m_names below -Kev */
2287   parv[2] = p = NULL;
2288
2289   *jbuf = *mbuf = '\0';         /* clear both join and mode buffers -Kev */
2290   /*
2291    *  Rebuild list of channels joined to be the actual result of the
2292    *  JOIN.  Note that "JOIN 0" is the destructive problem.
2293    */
2294   for (name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ","))
2295   {
2296     size_t len;
2297     if (MyConnect(sptr))
2298       clean_channelname(name);
2299     else if (IsLocalChannel(name))
2300       continue;
2301     if (*name == '0' && *(name + 1) == '\0')
2302     {
2303       /* Remove the user from all his channels -Kev */
2304       while ((lp = sptr->user->channel))
2305       {
2306         chptr = lp->value.chptr;
2307         if (!is_zombie(sptr, chptr))
2308           sendto_channel_butserv(chptr, sptr, PartFmt2,
2309               parv[0], chptr->chname, "Left all channels");
2310         remove_user_from_channel(sptr, chptr);
2311       }
2312       /* Just in case */
2313       *mbuf = *jbuf = '\0';
2314       mlen = jlen = 0;
2315     }
2316     else
2317     {                           /* not a /join 0, so treat it as
2318                                    a /join #channel -Kev */
2319       if (!IsChannelName(name))
2320       {
2321         if (MyUser(sptr))
2322           sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
2323         continue;
2324       }
2325
2326       if (MyConnect(sptr))
2327       { 
2328 #ifdef BADCHAN
2329         if(bad_channel(name) && !IsAnOper(sptr))
2330         {
2331           sendto_one(sptr, err_str(ERR_BADCHANNAME), me.name, parv[0],name);
2332           continue;
2333         }
2334 #endif
2335
2336         /*
2337          * Local client is first to enter previously nonexistant
2338          * channel so make them (rightfully) the Channel Operator.
2339          * This looks kind of ugly because we try to avoid calling the strlen()
2340          */
2341         if (ChannelExists(name))
2342         {
2343           flags = CHFL_DEOPPED;
2344           sendcreate = 0;
2345         }
2346         else if (strlen(name) > CHANNELLEN)
2347         {
2348           *(name + CHANNELLEN) = '\0';
2349           if (ChannelExists(name))
2350           {
2351             flags = CHFL_DEOPPED;
2352             sendcreate = 0;
2353           }
2354           else
2355           {
2356             flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
2357             sendcreate = 1;
2358           }
2359         }
2360         else
2361         {
2362           flags = IsModelessChannel(name) ? CHFL_DEOPPED : CHFL_CHANOP;
2363           sendcreate = 1;
2364         }
2365
2366 #ifdef OPER_NO_CHAN_LIMIT
2367         /*
2368          * Opers are allowed to join any number of channels
2369          */
2370         if (sptr->user->joined >= MAXCHANNELSPERUSER && !IsOper(sptr))
2371 #else
2372         if (sptr->user->joined >= MAXCHANNELSPERUSER)
2373 #endif
2374         {
2375           chptr = get_channel(sptr, name, !CREATE);
2376           sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
2377               me.name, parv[0], chptr ? chptr->chname : name);
2378           break;                /* Can't return, else he won't get on ANY
2379                                    channels!  Break out of the for loop instead.
2380                                    -Kev */
2381         }
2382       }
2383       chptr = get_channel(sptr, name, CREATE);
2384       if (chptr && (lp = find_user_link(chptr->members, sptr)))
2385       {
2386         if (lp->flags & CHFL_ZOMBIE)
2387         {
2388           zombie = 1;
2389           flags = lp->flags & (CHFL_DEOPPED | CHFL_SERVOPOK);
2390           remove_user_from_channel(sptr, chptr);
2391           chptr = get_channel(sptr, name, CREATE);
2392         }
2393         else
2394           continue;
2395       }
2396       name = chptr->chname;
2397       if (!chptr->creationtime) /* A remote JOIN created this channel ? */
2398         chptr->creationtime = MAGIC_REMOTE_JOIN_TS;
2399       if (parc > 2)
2400       {
2401         if (chptr->creationtime == MAGIC_REMOTE_JOIN_TS)
2402           chptr->creationtime = atoi(keysOrTS);
2403         else
2404           parc = 2;             /* Don't pass it on */
2405       }
2406       if (!zombie)
2407       {
2408         if (!MyConnect(sptr))
2409           flags = CHFL_DEOPPED;
2410         if (sptr->flags & FLAGS_TS8)
2411           flags |= CHFL_SERVOPOK;
2412       }
2413       if (MyConnect(sptr))
2414       {
2415         int created = chptr->users == 0;
2416         if (check_target_limit(sptr, chptr, chptr->chname, created))
2417         {
2418           if (created)          /* Did we create the channel? */
2419             sub1_from_channel(chptr);   /* Remove it again! */
2420           continue;
2421         }
2422         if ((i = can_join(sptr, chptr, keysOrTS)))
2423         {
2424           sendto_one(sptr, err_str(i), me.name, parv[0], chptr->chname);
2425           continue;
2426         }
2427       }
2428       /*
2429        * Complete user entry to the new channel (if any)
2430        */
2431       add_user_to_channel(chptr, sptr, flags);
2432
2433       /*
2434        * Notify all other users on the new channel
2435        */
2436       sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
2437
2438       if (MyUser(sptr))
2439       {
2440         del_invite(sptr, chptr);
2441         if (chptr->topic[0] != '\0')
2442         {
2443           sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
2444               parv[0], name, chptr->topic);
2445           sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0], name,
2446               chptr->topic_nick, chptr->topic_time);
2447         }
2448         parv[1] = name;
2449         m_names(cptr, sptr, 2, parv);
2450       }
2451     }
2452
2453     /* Select proper buffer; mbuf for creation, jbuf otherwise */
2454
2455     if (*name == '&')
2456       continue;                 /* Head off local channels at the pass */
2457
2458     bufptr = (sendcreate == 0) ? jbuf : mbuf;
2459     buflen = (sendcreate == 0) ? &jlen : &mlen;
2460     len = strlen(name);
2461     if (*buflen < BUFSIZE - len - 2)
2462     {
2463       if (*bufptr)
2464       {
2465         strcat(bufptr, ",");    /* Add to join buf */
2466         *buflen += 1;
2467       }
2468       strncat(bufptr, name, BUFSIZE - *buflen - 1);
2469       *buflen += len;
2470     }
2471     sendcreate = 0;             /* Reset sendcreate */
2472   }
2473
2474 #ifndef NO_PROTOCOL9
2475   if (*jbuf || *mbuf)           /* Propagate joins to P09 servers */
2476     sendto_lowprot_butone(cptr, 9, (*jbuf && *mbuf) ? ":%s JOIN %s,%s" :
2477         ":%s JOIN %s%s", parv[0], jbuf, mbuf);
2478 #endif
2479
2480   if (*jbuf)                    /* Propgate joins to P10 servers */
2481 #ifdef NO_PROTOCOL9
2482     sendto_serv_butone(cptr,
2483         parc > 2 ? ":%s JOIN %s %s" : ":%s JOIN %s", parv[0], jbuf, keysOrTS);
2484 #else
2485     sendto_highprot_butone(cptr, 10,
2486         parc > 2 ? ":%s JOIN %s %s" : ":%s JOIN %s", parv[0], jbuf, keysOrTS);
2487 #endif
2488   if (*mbuf)                    /* and now creation events */
2489 #ifdef NO_PROTOCOL9
2490     sendto_serv_butone(cptr, "%s%s CREATE %s " TIME_T_FMT,
2491         NumNick(sptr), mbuf, TStime());
2492 #else
2493     sendto_highprot_butone(cptr, 10, "%s%s CREATE %s " TIME_T_FMT,
2494         NumNick(sptr), mbuf, TStime());
2495 #endif
2496
2497   if (MyUser(sptr))
2498   {                             /* shouldn't ever set TS for remote JOIN's */
2499     if (*jbuf)
2500     {                           /* check for channels that need TS's */
2501       p = NULL;
2502       for (name = strtoken(&p, jbuf, ","); name; name = strtoken(&p, NULL, ","))
2503       {
2504         chptr = get_channel(sptr, name, !CREATE);
2505         if (chptr && chptr->mode.mode & MODE_SENDTS)
2506         {                       /* send a TS? */
2507           sendto_serv_butone(cptr, ":%s MODE %s + " TIME_T_FMT, me.name,
2508               chptr->chname, chptr->creationtime);      /* ok, send TS */
2509           chptr->mode.mode &= ~MODE_SENDTS;     /* reset flag */
2510         }
2511       }
2512     }
2513
2514     if (*mbuf)
2515     {                           /* ok, send along modes for creation events to P9 */
2516       p = NULL;
2517       for (name = strtoken(&p, mbuf, ","); name; name = strtoken(&p, NULL, ","))
2518       {
2519         chptr = get_channel(sptr, name, !CREATE);
2520         sendto_lowprot_butone(cptr, 9, ":%s MODE %s +o %s " TIME_T_FMT,
2521             me.name, chptr->chname, parv[0], chptr->creationtime);
2522       }
2523     }
2524   }
2525   return 0;
2526 }
2527
2528 /*
2529  * m_destruct
2530  *
2531  * parv[0] = sender prefix
2532  * parv[1] = channel channelname
2533  * parv[2] = channel time stamp
2534  *
2535  * This function does nothing, it does passes DESTRUCT to the other servers.
2536  * In the future we will start to use this message.
2537  *
2538  */
2539 int m_destruct(aClient *cptr, aClient *sptr, int parc, char *parv[])
2540 {
2541   time_t chanTS;                /* Creation time of the channel */
2542
2543   if (parc < 3 || *parv[2] == '\0')
2544     return 0;
2545
2546 #ifdef GODMODE
2547   /* Allow DESTRUCT from user */
2548   if (MyUser(sptr))
2549     sptr = &me;
2550   else
2551 #endif
2552
2553     /* sanity checks: Only accept DESTRUCT messages from servers */
2554   if (!IsServer(sptr))
2555     return 0;
2556
2557   /* Don't pass on DESTRUCT messages for channels that exist */
2558   if (FindChannel(parv[1]))
2559     return 0;
2560
2561   chanTS = atoi(parv[2]);
2562
2563   /* Pass on DESTRUCT message */
2564   sendto_highprot_butone(cptr, 10, "%s DESTRUCT %s " TIME_T_FMT,
2565       NumServ(sptr), parv[1], chanTS);
2566
2567   return 0;
2568 }
2569
2570 /*
2571  * m_create
2572  *
2573  * parv[0] = sender prefix
2574  * parv[1] = channel names
2575  * parv[2] = channel time stamp
2576  */
2577 int m_create(aClient *cptr, aClient *sptr, int parc, char *parv[])
2578 {
2579   char cbuf[BUFSIZE];           /* Buffer for list with channels
2580                                    that `sptr' really creates */
2581   time_t chanTS;                /* Creation time for all channels
2582                                    in the comma seperated list */
2583   char *p, *name;
2584   Reg5 aChannel *chptr;
2585   int badop;
2586
2587   /* sanity checks: Only accept CREATE messages from servers */
2588   if (!IsServer(cptr) || parc < 3 || *parv[2] == '\0')
2589     return 0;
2590
2591   chanTS = atoi(parv[2]);
2592
2593   *cbuf = '\0';                 /* Start with empty buffer */
2594
2595   /* For each channel in the comma seperated list: */
2596   for (name = strtoken(&p, parv[1], ","); name; name = strtoken(&p, NULL, ","))
2597   {
2598     badop = 0;                  /* Default is to accept the op */
2599     if ((chptr = FindChannel(name)))
2600     {
2601       name = chptr->chname;
2602       if (TStime() - chanTS > TS_LAG_TIME)
2603       {
2604         /* A bounce would not be accepted anyway - if we get here something
2605            is wrong with the TS clock syncing (or we have more then
2606            TS_LAG_TIME lag, or an admin is hacking */
2607         badop = 2;
2608         /* This causes a HACK notice on all upstream servers: */
2609         if (Protocol(cptr) < 10)
2610           sendto_one(cptr, ":%s MODE %s -o %s 0", me.name, name, sptr->name);
2611         else
2612           sendto_one(cptr, ":%s MODE %s -o %s%s 0",
2613               me.name, name, NumNick(sptr));
2614         /* This causes a WALLOPS on all downstream servers and a notice to our
2615            own opers: */
2616         parv[1] = name;         /* Corrupt parv[1], it is not used anymore anyway */
2617         send_hack_notice(cptr, sptr, parc, parv, badop, 2);
2618       }
2619       else if (chptr->creationtime && chanTS > chptr->creationtime &&
2620           chptr->creationtime != MAGIC_REMOTE_JOIN_TS)
2621       {
2622         /* We (try) to bounce the mode, because the CREATE is used on an older
2623            channel, probably a net.ride */
2624         badop = 1;
2625         /* Send a deop upstream: */
2626         if (Protocol(cptr) < 10)
2627           sendto_one(cptr, ":%s MODE %s -o %s " TIME_T_FMT, me.name,
2628               name, sptr->name, chptr->creationtime);
2629         else
2630           sendto_one(cptr, ":%s MODE %s -o %s%s " TIME_T_FMT, me.name,
2631               name, NumNick(sptr), chptr->creationtime);
2632       }
2633     }
2634     else                        /* Channel doesn't exist: create it */
2635       chptr = get_channel(sptr, name, CREATE);
2636
2637     /* Add and mark ops */
2638     add_user_to_channel(chptr, sptr,
2639         (badop || IsModelessChannel(name)) ? CHFL_DEOPPED : CHFL_CHANOP);
2640
2641     /* Send user join to the local clients (if any) */
2642     sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
2643
2644     if (badop)                  /* handle badop: convert CREATE into JOIN */
2645       sendto_serv_butone(cptr, ":%s JOIN %s " TIME_T_FMT,
2646           sptr->name, name, chptr->creationtime);
2647     else
2648     {
2649       /* Send the op to local clients:
2650          (if any; extremely unlikely, but it CAN happen) */
2651       if (!IsModelessChannel(name))
2652         sendto_channel_butserv(chptr, sptr, ":%s MODE %s +o %s",
2653             sptr->user->server->name, name, parv[0]);
2654
2655       /* Set/correct TS and add the channel to the
2656          buffer for accepted channels: */
2657       chptr->creationtime = chanTS;
2658       if (*cbuf)
2659         strcat(cbuf, ",");
2660       strcat(cbuf, name);
2661     }
2662   }
2663
2664   if (*cbuf)                    /* Any channel accepted with ops ? */
2665   {
2666 #ifdef NO_PROTOCOL9
2667     sendto_serv_butone(cptr, "%s%s CREATE %s " TIME_T_FMT,
2668         NumNick(sptr), cbuf, chanTS);
2669 #else
2670     /* send CREATEs to 2.10 servers */
2671     sendto_highprot_butone(cptr, 10, "%s%s CREATE %s " TIME_T_FMT,
2672         NumNick(sptr), cbuf, chanTS);
2673
2674     /* And JOIN + MODE to 2.9 servers; following
2675        is not needed after all are 2.10 */
2676     sendto_lowprot_butone(cptr, 9, ":%s JOIN %s", parv[0], cbuf);
2677     p = NULL;
2678     for (name = strtoken(&p, cbuf, ","); name; name = strtoken(&p, NULL, ","))
2679       sendto_lowprot_butone(cptr, 9, ":%s MODE %s +o %s " TIME_T_FMT,
2680           sptr->user->server->name, name, parv[0], chanTS);
2681 #endif
2682   }
2683
2684   return 0;
2685 }
2686
2687 static size_t prefix_len;
2688
2689 static void add_token_to_sendbuf(char *token, size_t *sblenp, int *firstp,
2690     int *send_itp, char is_a_ban, int mode)
2691 {
2692   int first = *firstp;
2693
2694   /*
2695    * Heh - we do not need to test if it still fits in the buffer, because
2696    * this BURST message is reconstructed from another BURST message, and
2697    * it only can become smaller. --Run
2698    */
2699
2700   if (*firstp)                  /* First token in this parameter ? */
2701   {
2702     *firstp = 0;
2703     if (*send_itp == 0)
2704       *send_itp = 1;            /* Buffer contains data to be sent */
2705     sendbuf[(*sblenp)++] = ' ';
2706     if (is_a_ban)
2707     {
2708       sendbuf[(*sblenp)++] = ':';       /* Bans are always the last "parv" */
2709       sendbuf[(*sblenp)++] = is_a_ban;
2710     }
2711   }
2712   else                          /* Of course, 'send_it' is already set here */
2713     /* Seperate banmasks with a space because
2714        they can contain commas themselfs: */
2715     sendbuf[(*sblenp)++] = is_a_ban ? ' ' : ',';
2716   strcpy(sendbuf + *sblenp, token);
2717   *sblenp += strlen(token);
2718   if (!is_a_ban)                /* nick list ? Need to take care
2719                                    of modes for nicks: */
2720   {
2721     static int last_mode = 0;
2722     mode &= CHFL_CHANOP | CHFL_VOICE;
2723     if (first)
2724       last_mode = 0;
2725     if (last_mode != mode)      /* Append mode like ':ov' if changed */
2726     {
2727       last_mode = mode;
2728       sendbuf[(*sblenp)++] = ':';
2729       if (mode & CHFL_CHANOP)
2730         sendbuf[(*sblenp)++] = 'o';
2731       if (mode & CHFL_VOICE)
2732         sendbuf[(*sblenp)++] = 'v';
2733     }
2734     sendbuf[*sblenp] = '\0';
2735   }
2736 }
2737
2738 static void cancel_mode(aClient *sptr, aChannel *chptr, char m,
2739     const char *param, int *count)
2740 {
2741   static char *pb, *sbp, *sbpi;
2742   int paramdoesntfit = 0;
2743   if (*count == -1)             /* initialize ? */
2744   {
2745     sbp = sbpi =
2746         sprintf_irc(sendbuf, ":%s MODE %s -", sptr->name, chptr->chname);
2747     pb = parabuf;
2748     *count = 0;
2749   }
2750   /* m == 0 means flush */
2751   if (m)
2752   {
2753     if (param)
2754     {
2755       size_t nplen = strlen(param);
2756       if (pb - parabuf + nplen + 23 > MODEBUFLEN)
2757         paramdoesntfit = 1;
2758       else
2759       {
2760         *sbp++ = m;
2761         *pb++ = ' ';
2762         strcpy(pb, param);
2763         pb += nplen;
2764         ++*count;
2765       }
2766     }
2767     else
2768       *sbp++ = m;
2769   }
2770   else if (*count == 0)
2771     return;
2772   if (*count == 6 || !m || paramdoesntfit)
2773   {
2774 #ifndef NO_PROTOCOL9
2775     Dlink *lp;
2776     char *sbe;
2777 #endif
2778     Link *member;
2779     strcpy(sbp, parabuf);
2780 #ifndef NO_PROTOCOL9
2781     sbe = sbp + strlen(parabuf);
2782 #endif
2783     for (member = chptr->members; member; member = member->next)
2784       if (MyUser(member->value.cptr))
2785         sendbufto_one(member->value.cptr);
2786 #ifndef NO_PROTOCOL9
2787     sprintf_irc(sbe, " " TIME_T_FMT, chptr->creationtime);
2788     /* Send 'sendbuf' to all 2.9 downlinks: */
2789     for (lp = me.serv->down; lp; lp = lp->next)
2790       if (Protocol(lp->value.cptr) < 10)
2791         sendbufto_one(lp->value.cptr);
2792 #endif
2793     sbp = sbpi;
2794     pb = parabuf;
2795     *count = 0;
2796   }
2797   if (paramdoesntfit)
2798   {
2799     *sbp++ = m;
2800     *pb++ = ' ';
2801     strcpy(pb, param);
2802     pb += strlen(param);
2803     ++*count;
2804   }
2805 }
2806
2807 /*
2808  * m_burst  --  by Run carlo@runaway.xs4all.nl  december 1995 till march 1997
2809  *
2810  * parv[0] = sender prefix
2811  * parv[1] = channel name
2812  * parv[2] = channel timestamp
2813  * The meaning of the following parv[]'s depend on their first character:
2814  * If parv[n] starts with a '+':
2815  * Net burst, additive modes
2816  *   parv[n] = <mode>
2817  *   parv[n+1] = <param> (optional)
2818  *   parv[n+2] = <param> (optional)
2819  * If parv[n] starts with a '%', then n will be parc-1:
2820  *   parv[n] = %<ban> <ban> <ban> ...
2821  * If parv[n] starts with another character:
2822  *   parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
2823  *   where <mode> is the channel mode (ov) of nick and all following nicks.
2824  *
2825  * Example:
2826  * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
2827  *
2828  * Anti net.ride code.
2829  *
2830  * When the channel already exist, and its TS is larger then
2831  * the TS in the BURST message, then we cancel all existing modes.
2832  * If its is smaller then the received BURST message is ignored.
2833  * If it's equal, then the received modes are just added.
2834  */
2835 int m_burst(aClient *cptr, aClient *sptr, int parc, char *parv[])
2836 {
2837   Reg1 aChannel *chptr;
2838   time_t timestamp;
2839   int netride = 0, wipeout = 0, n;
2840   int send_it = 0, add_banid_not_called = 1;
2841   Mode *current_mode;
2842   size_t sblen, mblen = 0;
2843   int mblen2, pblen2, cnt;
2844   int prev_mode;
2845   char prev_key[KEYLEN + 1];
2846   Link *lp;
2847 #ifndef NO_PROTOCOL9
2848   int ts_sent = 0;
2849 #endif
2850
2851   /* BURST is only for servers and has at least 4 parameters */
2852   if (!IsServer(cptr) || parc < 4)
2853     return 0;
2854
2855   if (!IsBurst(sptr))
2856   {
2857     int i;
2858     char *p;
2859     if (find_conf_host(cptr->confs, sptr->name, CONF_UWORLD))
2860     {
2861       p =
2862           sprintf_irc(sendbuf,
2863           ":%s NOTICE * :*** Notice -- HACK(4): %s BURST %s %s", me.name,
2864           sptr->name, parv[1], parv[2]);
2865       for (i = 3; i < parc - 1; ++i)
2866         p = sprintf_irc(p, " %s", parv[i]);
2867       sprintf_irc(p, " :%s", parv[parc - 1]);
2868       sendbufto_op_mask(SNO_HACK4);
2869     }
2870     else
2871     {
2872 #if 1                           /* FIXME: This should be removed after all HUBs upgraded to ircu2.10.05 */
2873       SetBurst(sptr);
2874       if (MyConnect(sptr))
2875 #endif
2876         return exit_client_msg(cptr, cptr, &me,
2877             "HACK: BURST message outside net.burst from %s", sptr->name);
2878     }
2879   }
2880
2881   /* Find the channel, or create it - note that the creation time
2882    * will be 0 if it has to be created */
2883   chptr = get_channel(sptr, parv[1], CREATE);
2884   current_mode = &chptr->mode;
2885   prev_mode = chptr->mode.mode;
2886   if (*chptr->mode.key)
2887   {
2888     prev_mode |= MODE_KEY;
2889     strcpy(prev_key, chptr->mode.key);
2890   }
2891   if (chptr->mode.limit)
2892     prev_mode |= MODE_LIMIT;
2893
2894   timestamp = atoi(parv[2]);
2895
2896   /* Copy the new TS when the received creationtime appears to be older */
2897   if (!chptr->creationtime || chptr->creationtime > timestamp)
2898   {
2899     /* Set the new timestamp */
2900     chptr->creationtime = timestamp;
2901     send_it = 1;                /* Make sure we pass on the different timestamp ! */
2902     /* Mark all bans as needed to be wiped out */
2903     for (lp = chptr->banlist; lp; lp = lp->next)
2904       lp->flags |= CHFL_BURST_BAN_WIPEOUT;
2905     /*
2906      * Only the first BURST for this channel can have creationtime > timestamp,
2907      * so at this moment ALL members are on OUR side, and thus all net.riders:
2908      */
2909     wipeout = 1;
2910   }
2911   for (lp = chptr->members; lp; lp = lp->next)
2912     lp->flags &= ~CHFL_BURST_JOINED;    /* Set later for nicks in the BURST msg */
2913   /* If `wipeout' is set then these will be deopped later. */
2914
2915   /* If the entering creationtime is younger, ignore the modes */
2916   if (chptr->creationtime < timestamp)
2917     netride = 1;                /* Only pass on the nicks (so they JOIN) */
2918
2919   /* Prepare buffers to pass the message */
2920   *bparambuf = *bmodebuf = *parabuf = '\0';
2921   pblen2 = 0;
2922   *modebuf = '+';
2923   mblen2 = 1;
2924   cnt = 0;
2925   prefix_len = sblen = sprintf_irc(sendbuf, "%s BURST %s " TIME_T_FMT,
2926       NumServ(sptr), chptr->chname, chptr->creationtime) - sendbuf;
2927
2928   /* Run over all remaining parameters */
2929   for (n = 3; n < parc; n++)
2930     switch (*parv[n])           /* What type is it ? mode, nicks or bans ? */
2931     {
2932       case '+':         /* modes */
2933       {
2934         char *p = parv[n];
2935         while (*(++p))          /* Run over all mode characters */
2936         {
2937           switch (*p)           /* which mode ? */
2938           {
2939               /*
2940                * The following cases all do the following:
2941                * - In case wipeout needed, reset 'prev_mode' to indicate this
2942                *   mode should not be cancelled.
2943                * - If wipeout or (not netride and the new mode is a change),
2944                *   add it to bmodebuf and bparabuf for propagation.
2945                * - Else ignore it.
2946                * - Add it to modebuf and parabuf for propagation to the
2947                *   clients when not netride and the new mode is a change.
2948                * Special cases:
2949                * - If a +s is received, cancel a +p and sent a -p to the
2950                *   clients too (if +p was set).
2951                * - If a +p is received and +s is set, ignore the +p.
2952                */
2953             case 'i':
2954             {
2955               register int tmp;
2956               prev_mode &= ~MODE_INVITEONLY;
2957               if (!(tmp = netride ||
2958                   (current_mode->mode & MODE_INVITEONLY)) || wipeout)
2959               {
2960                 bmodebuf[mblen++] = 'i';
2961                 current_mode->mode |= MODE_INVITEONLY;
2962               }
2963               if (!tmp)
2964                 modebuf[mblen2++] = 'i';
2965               break;
2966             }
2967             case 'k':
2968             {
2969               register int tmp;
2970               char *param = parv[++n];
2971               prev_mode &= ~MODE_KEY;
2972               if (!(tmp = netride || (*current_mode->key &&
2973                   (!strcmp(current_mode->key, param) ||
2974                   (!wipeout && strcmp(current_mode->key, param) < 0)))) ||
2975                   wipeout)
2976               {
2977                 bmodebuf[mblen++] = 'k';
2978                 strcat(bparambuf, " ");
2979                 strcat(bparambuf, param);
2980                 strncpy(current_mode->key, param, KEYLEN);
2981               }
2982               if (!tmp && !wipeout)
2983               {
2984                 modebuf[mblen2++] = 'k';
2985                 parabuf[pblen2++] = ' ';
2986                 strcpy(parabuf + pblen2, param);
2987                 pblen2 += strlen(param);
2988                 cnt++;
2989               }
2990               break;
2991             }
2992             case 'l':
2993             {
2994               register int tmp;
2995               unsigned int param = atoi(parv[++n]);
2996               prev_mode &= ~MODE_LIMIT;
2997               if (!(tmp = netride || (current_mode->limit &&
2998                   (current_mode->limit == param ||
2999                   (!wipeout && current_mode->limit < param)))) || wipeout)
3000               {
3001                 bmodebuf[mblen++] = 'l';
3002                 sprintf_irc(bparambuf + strlen(bparambuf), " %d", param);
3003                 current_mode->limit = param;
3004               }
3005               if (!tmp)
3006               {
3007                 modebuf[mblen2++] = 'l';
3008                 pblen2 = sprintf_irc(parabuf + pblen2, " %d", param) - parabuf;
3009                 cnt++;
3010               }
3011               break;
3012             }
3013             case 'm':
3014             {
3015               register int tmp;
3016               prev_mode &= ~MODE_MODERATED;
3017               if (!(tmp = netride ||
3018                   (current_mode->mode & MODE_MODERATED)) || wipeout)
3019               {
3020                 bmodebuf[mblen++] = 'm';
3021                 current_mode->mode |= MODE_MODERATED;
3022               }
3023               if (!tmp)
3024                 modebuf[mblen2++] = 'm';
3025               break;
3026             }
3027             case 'n':
3028             {
3029               register int tmp;
3030               prev_mode &= ~MODE_NOPRIVMSGS;
3031               if (!(tmp = netride ||
3032                   (current_mode->mode & MODE_NOPRIVMSGS)) || wipeout)
3033               {
3034                 bmodebuf[mblen++] = 'n';
3035                 current_mode->mode |= MODE_NOPRIVMSGS;
3036               }
3037               if (!tmp)
3038                 modebuf[mblen2++] = 'n';
3039               break;
3040             }
3041             case 'p':
3042             {
3043               register int tmp;
3044
3045               /* Special case: */
3046               if (!netride && !wipeout && (current_mode->mode & MODE_SECRET))
3047                 break;
3048
3049               prev_mode &= ~MODE_PRIVATE;
3050               if (!(tmp = netride ||
3051                   (current_mode->mode & MODE_PRIVATE)) || wipeout)
3052               {
3053                 bmodebuf[mblen++] = 'p';
3054                 current_mode->mode |= MODE_PRIVATE;
3055               }
3056               if (!tmp)
3057                 modebuf[mblen2++] = 'p';
3058               break;
3059             }
3060             case 's':
3061             {
3062               register int tmp;
3063               prev_mode &= ~MODE_SECRET;
3064               if (!(tmp = netride ||
3065                   (current_mode->mode & MODE_SECRET)) || wipeout)
3066               {
3067                 bmodebuf[mblen++] = 's';
3068                 current_mode->mode |= MODE_SECRET;
3069               }
3070               if (!tmp)
3071                 modebuf[mblen2++] = 's';
3072
3073               /* Special case: */
3074               if (!netride && !wipeout && (current_mode->mode & MODE_PRIVATE))
3075               {
3076                 int i;
3077                 for (i = mblen2 - 1; i >= 0; --i)
3078                   modebuf[i + 2] = modebuf[i];
3079                 modebuf[0] = '-';
3080                 modebuf[1] = 'p';
3081                 mblen2 += 2;
3082                 current_mode->mode &= ~MODE_PRIVATE;
3083               }
3084
3085               break;
3086             }
3087             case 't':
3088             {
3089               register int tmp;
3090               prev_mode &= ~MODE_TOPICLIMIT;
3091               if (!(tmp = netride ||
3092                   (current_mode->mode & MODE_TOPICLIMIT)) || wipeout)
3093               {
3094                 bmodebuf[mblen++] = 't';
3095                 current_mode->mode |= MODE_TOPICLIMIT;
3096               }
3097               if (!tmp)
3098                 modebuf[mblen2++] = 't';
3099               break;
3100             }
3101           }
3102         }                       /* <-- while over all modes */
3103
3104         bmodebuf[mblen] = '\0';
3105         sendbuf[sblen] = '\0';
3106         if (mblen)              /* Anything to send at all ? */
3107         {
3108           send_it = 1;
3109           strcpy(sendbuf + sblen, " +");
3110           sblen += 2;
3111           strcpy(sendbuf + sblen, bmodebuf);
3112           sblen += mblen;
3113           strcpy(sendbuf + sblen, bparambuf);
3114           sblen += strlen(bparambuf);
3115         }
3116         break;                  /* Done mode part */
3117       }
3118       case '%':         /* bans */
3119       {
3120         char *pv, *p = NULL, *ban;
3121         int first = 1;
3122         if (netride)
3123           break;                /* Ignore bans */
3124         /* Run over all bans */
3125         for (pv = parv[n] + 1; (ban = strtoken(&p, pv, " ")); pv = NULL)
3126         {
3127           int ret;
3128           /*
3129            * The following part should do the following:
3130            * - If the new (un)ban is not a _change_ it is ignored.
3131            * - Else, add it to sendbuf for later use.
3132            * - If sendbuf is full, send it, and prepare a new
3133            *   message in sendbuf.
3134            */
3135           ret = add_banid(sptr, chptr, ban, 1, add_banid_not_called);
3136           if (ret == 0)
3137           {
3138             add_banid_not_called = 0;
3139             /* Mark this new ban so we can send it to the clients later */
3140             chptr->banlist->flags |= CHFL_BURST_BAN;
3141           }
3142           if (ret != -1)
3143             /* A new ban was added or an existing one needs to be passed on.
3144              * Also add it to sendbuf: */
3145             add_token_to_sendbuf(ban, &sblen, &first, &send_it, '%', 0);
3146         }
3147         break;                  /* Done bans part */
3148       }
3149       default:                  /* nicks */
3150       {
3151         char *pv, *p = NULL, *nick, *ptr;
3152         int first = 1;
3153         /* Default mode: */
3154         int default_mode = CHFL_DEOPPED;
3155         /* Run over all nicks */
3156         for (pv = parv[n]; (nick = strtoken(&p, pv, ",")); pv = NULL)
3157         {
3158           aClient *acptr;
3159           if ((ptr = strchr(nick, ':')))        /* New default mode ? */
3160           {
3161             *ptr = '\0';        /* Fix 'nick' */
3162             acptr = findNUser(nick);
3163             if (!netride)
3164             {
3165               /* Calculate new mode change: */
3166               default_mode = CHFL_DEOPPED;
3167               while (*(++ptr))
3168                 if (*ptr == 'o')
3169                 {
3170                   default_mode |= CHFL_CHANOP;
3171                   default_mode &= ~CHFL_DEOPPED;
3172                 }
3173                 else if (*ptr == 'v')
3174                   default_mode |= CHFL_VOICE;
3175                 else
3176                   break;
3177             }
3178           }
3179           else
3180             acptr = findNUser(nick);
3181           /*
3182            * Note that at this point we already received a 'NICK' for any
3183            * <nick> numeric that is joining (and possibly opped) here.
3184            * Therefore we consider the following situations:
3185            * - The <nick> numeric exists and is from the direction of cptr: ok
3186            * - The <nick> numeric does not exist:
3187            *   Apparently this previous <nick> numeric was killed (upstream)
3188            *   or it collided with an existing <nick> name.
3189            * - The <nick> numeric exists but is from another direction:
3190            *   Apparently this previous <nick> numeric was killed,
3191            *   and due to a reroute it signed on via another link (probably
3192            *   a nick [numeric] collision).
3193            * Note that it can't be a QUIT or SQUIT, because a QUIT would
3194            * come from the same direction as the BURST (cptr) while an
3195            * upstream SQUIT removes the source (server) and we would thus
3196            * have this BURST ignored already.
3197            * This means that if we find the nick and it is from the correct
3198            * direction, it joins. If it doesn't exist or is from another
3199            * direction, we have to ignore it. If all nicks are ignored, we
3200            * remove the channel again when it is empty and don't propagate
3201            * the BURST message.
3202            */
3203           if (acptr && acptr->from == cptr)
3204           {
3205             /*
3206              * The following should do the following:
3207              * - Add it to sendbuf for later use.
3208              * - If sendbuf is full, send it, and prepare a new
3209              *   message in sendbuf.
3210              */
3211             add_token_to_sendbuf(nick, &sblen, &first, &send_it, 0,
3212                 default_mode);
3213             /* Let is take effect: (Note that in the case of a netride
3214              * 'default_mode' is always CHFL_DEOPPED here). */
3215             add_user_to_channel(chptr, acptr, default_mode);
3216             chptr->members->flags |= CHFL_BURST_JOINED;
3217           }
3218         }                       /* <-- Next nick */
3219         if (!chptr->members)    /* All nicks collided and channel is empty ? */
3220         {
3221           sub1_from_channel(chptr);
3222           return 0;             /* Forget about the (rest of the) message... */
3223         }
3224         break;                  /* Done nicks part */
3225       }
3226     }                           /* <-- Next parameter if any */
3227   if (!chptr->members)          /* This message only contained bans (then the previous
3228                                    message only contained collided nicks, see above) */
3229   {
3230     sub1_from_channel(chptr);
3231     if (!add_banid_not_called)
3232       while (next_removed_overlapped_ban());
3233     return 0;                   /* Forget about the (rest of the) message... */
3234   }
3235
3236   /* The last (possibly only) message is always send here */
3237   if (send_it)                  /* Anything (left) to send ? */
3238   {
3239     Dlink *lp;
3240     Link *member;
3241
3242     /* send 'sendbuf' to all downlinks */
3243     for (lp = me.serv->down; lp; lp = lp->next)
3244     {
3245       if (lp->value.cptr == cptr)
3246         continue;
3247       if (Protocol(lp->value.cptr) > 9)
3248         sendbufto_one(lp->value.cptr);
3249     }
3250
3251     /*
3252      * Now we finally can screw sendbuf again...
3253      * Send all changes to the local clients:
3254      *
3255      * First send all joins and op them, because 2.9 servers
3256      * would protest with a HACK if we first de-opped people.
3257      * However, we don't send the +b bans yes, because we
3258      * DO first want to -b the old bans (otherwise it's confusing).
3259      */
3260
3261     /* Send all joins: */
3262     for (member = chptr->members; member; member = member->next)
3263       if (member->flags & CHFL_BURST_JOINED)
3264       {
3265         sendto_channel_butserv(chptr, member->value.cptr, ":%s JOIN :%s",
3266             member->value.cptr->name, chptr->chname);
3267 #ifndef NO_PROTOCOL9
3268         /* And to 2.9 servers: */
3269         sendto_lowprot_butone(cptr, 9, ":%s JOIN %s",
3270             member->value.cptr->name, chptr->chname);
3271 #endif
3272       }
3273
3274     if (!netride)
3275     {
3276       /* Send all +o and +v modes: */
3277       for (member = chptr->members; member; member = member->next)
3278       {
3279         if ((member->flags & CHFL_BURST_JOINED))
3280         {
3281           int mode = CHFL_CHANOP;
3282           for (;;)
3283           {
3284             if ((member->flags & mode))
3285             {
3286               modebuf[mblen2++] = (mode == CHFL_CHANOP) ? 'o' : 'v';
3287               parabuf[pblen2++] = ' ';
3288               strcpy(parabuf + pblen2, member->value.cptr->name);
3289               pblen2 += strlen(member->value.cptr->name);
3290               if (6 == ++cnt)
3291               {
3292                 modebuf[mblen2] = 0;
3293                 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3294                     parv[0], chptr->chname, modebuf, parabuf);
3295 #ifndef NO_PROTOCOL9
3296                 sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3297                     parv[0], chptr->chname, modebuf, parabuf,
3298                     chptr->creationtime);
3299                 ts_sent = 1;
3300 #endif
3301                 *parabuf = 0;
3302                 pblen2 = 0;
3303                 mblen2 = 1;
3304                 cnt = 0;
3305               }
3306             }
3307             if (mode == CHFL_CHANOP)
3308               mode = CHFL_VOICE;
3309             else
3310               break;
3311           }
3312         }
3313       }
3314       /* Flush MODEs: */
3315       if (cnt > 0 || mblen2 > 1)
3316       {
3317         modebuf[mblen2] = 0;
3318         sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3319             parv[0], chptr->chname, modebuf, parabuf);
3320 #ifndef NO_PROTOCOL9
3321         sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3322             parv[0], chptr->chname, modebuf, parabuf, chptr->creationtime);
3323         ts_sent = 1;
3324 #endif
3325       }
3326 #ifndef NO_PROTOCOL9
3327       else if (send_it && !ts_sent)
3328       {
3329         sendto_lowprot_butone(cptr, 9, ":%s MODE %s + " TIME_T_FMT,
3330             parv[0], chptr->chname, chptr->creationtime);
3331         ts_sent = 1;
3332       }
3333 #endif
3334     }
3335   }
3336
3337   if (wipeout)
3338   {
3339     Link *lp;
3340     Link **ban;
3341     int mode;
3342     char m;
3343     int count = -1;
3344
3345     /* Now cancel all previous simple modes */
3346     if ((prev_mode & MODE_SECRET))
3347       cancel_mode(sptr, chptr, 's', NULL, &count);
3348     if ((prev_mode & MODE_PRIVATE))
3349       cancel_mode(sptr, chptr, 'p', NULL, &count);
3350     if ((prev_mode & MODE_MODERATED))
3351       cancel_mode(sptr, chptr, 'm', NULL, &count);
3352     if ((prev_mode & MODE_TOPICLIMIT))
3353       cancel_mode(sptr, chptr, 't', NULL, &count);
3354     if ((prev_mode & MODE_INVITEONLY))
3355       cancel_mode(sptr, chptr, 'i', NULL, &count);
3356     if ((prev_mode & MODE_NOPRIVMSGS))
3357       cancel_mode(sptr, chptr, 'n', NULL, &count);
3358     if ((prev_mode & MODE_LIMIT))
3359     {
3360       current_mode->limit = 0;
3361       cancel_mode(sptr, chptr, 'l', NULL, &count);
3362     }
3363     if ((prev_mode & MODE_KEY))
3364     {
3365       *current_mode->key = 0;
3366       cancel_mode(sptr, chptr, 'k', prev_key, &count);
3367     }
3368     current_mode->mode &= ~prev_mode;
3369
3370     /* And deop and devoice all net.riders on my side */
3371     mode = CHFL_CHANOP;
3372     m = 'o';
3373     for (;;)
3374     {
3375       for (lp = chptr->members; lp; lp = lp->next)
3376       {
3377         if ((lp->flags & CHFL_BURST_JOINED))
3378           continue;             /* This is not a net.rider from
3379                                    this side of the net.junction */
3380         if ((lp->flags & mode))
3381         {
3382           lp->flags &= ~mode;
3383           if (mode == CHFL_CHANOP)
3384             lp->flags |= CHFL_DEOPPED;
3385           cancel_mode(sptr, chptr, m, lp->value.cptr->name, &count);
3386         }
3387       }
3388       if (mode == CHFL_VOICE)
3389         break;
3390       mode = CHFL_VOICE;
3391       m = 'v';
3392     }
3393
3394     /* And finally wipeout all bans that are left */
3395     for (ban = &chptr->banlist; *ban;)
3396     {
3397       Link *tmp = *ban;
3398       if ((tmp->flags & CHFL_BURST_BAN_WIPEOUT))
3399       {
3400         cancel_mode(sptr, chptr, 'b', tmp->value.ban.banstr, &count);
3401         /* Copied from del_banid(): */
3402         *ban = tmp->next;
3403         RunFree(tmp->value.ban.banstr);
3404         RunFree(tmp->value.ban.who);
3405         free_link(tmp);
3406         /* Erase ban-valid-bit, for channel members that are banned */
3407         for (tmp = chptr->members; tmp; tmp = tmp->next)
3408           if ((tmp->flags & (CHFL_BANNED | CHFL_BANVALID)) ==
3409               (CHFL_BANNED | CHFL_BANVALID))
3410             tmp->flags &= ~CHFL_BANVALID;       /* `tmp' == channel member */
3411       }
3412       else
3413         ban = &tmp->next;
3414     }
3415     /* Also wipeout overlapped bans */
3416     if (!add_banid_not_called)
3417     {
3418       Link *ban;
3419       while ((ban = next_removed_overlapped_ban()))
3420         cancel_mode(sptr, chptr, 'b', ban->value.ban.banstr, &count);
3421     }
3422     cancel_mode(sptr, chptr, 0, NULL, &count);  /* flush */
3423   }
3424
3425   if (send_it && !netride)
3426   {
3427     Link *bl;
3428     int deban;
3429
3430     if (add_banid_not_called || !(bl = next_removed_overlapped_ban()))
3431     {
3432       deban = 0;
3433       bl = chptr->banlist;
3434       *modebuf = '+';
3435     }
3436     else
3437     {
3438       deban = 1;
3439       *modebuf = '-';
3440     }
3441
3442     mblen2 = 1;
3443     pblen2 = 0;
3444     cnt = 0;
3445     for (;;)
3446     {
3447       size_t nblen = 0;
3448       if (bl)
3449         nblen = strlen(bl->value.ban.banstr);
3450       if (cnt == 6 || (!bl && cnt) || pblen2 + nblen + 12 > MODEBUFLEN) /* The last check is to make sure
3451                                                                            that the receiving 2.9 will
3452                                                                            still process this */
3453       {
3454         /* Time to send buffer */
3455         modebuf[mblen2] = 0;
3456         sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3457             parv[0], chptr->chname, modebuf, parabuf);
3458 #ifndef NO_PROTOCOL9
3459         sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s",
3460             parv[0], chptr->chname, modebuf, parabuf);
3461 #endif
3462         *modebuf = deban ? '-' : '+';
3463         mblen2 = 1;
3464         pblen2 = 0;
3465         cnt = 0;
3466       }
3467       if (!bl)                  /* Done ? */
3468         break;
3469       if (deban || (bl->flags & CHFL_BURST_BAN))
3470       {
3471         /* Add ban to buffers and remove it */
3472         modebuf[mblen2++] = 'b';
3473         parabuf[pblen2++] = ' ';
3474         strcpy(parabuf + pblen2, bl->value.ban.banstr);
3475         pblen2 += nblen;
3476         cnt++;
3477         bl->flags &= ~CHFL_BURST_BAN;
3478       }
3479       if (deban)
3480       {
3481         if (!(bl = next_removed_overlapped_ban()))
3482         {
3483           deban = 0;
3484           modebuf[mblen2++] = '+';
3485           bl = chptr->banlist;
3486         }
3487       }
3488       else
3489         bl = bl->next;
3490     }
3491     /* Flush MODE [-b]+b ...: */
3492     if (cnt > 0 || mblen2 > 1)
3493     {
3494       modebuf[mblen2] = 0;
3495       sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
3496           parv[0], chptr->chname, modebuf, parabuf);
3497 #ifndef NO_PROTOCOL9
3498       sendto_lowprot_butone(cptr, 9, ":%s MODE %s %s%s " TIME_T_FMT,
3499           parv[0], chptr->chname, modebuf, parabuf, chptr->creationtime);
3500 #endif
3501     }
3502 #ifndef NO_PROTOCOL9
3503     else if (send_it && !ts_sent)
3504       sendto_lowprot_butone(cptr, 9, ":%s MODE %s + " TIME_T_FMT,
3505           parv[0], chptr->chname, chptr->creationtime);
3506 #endif
3507   }
3508
3509   return 0;
3510 }
3511
3512 /*
3513  * m_part
3514  *
3515  * parv[0] = sender prefix
3516  * parv[1] = channel
3517  * parv[parc - 1] = comment
3518  */
3519 int m_part(aClient *cptr, aClient *sptr, int parc, char *parv[])
3520 {
3521   Reg1 aChannel *chptr;
3522   Reg2 Link *lp;
3523   char *p = NULL, *name, pbuf[BUFSIZE];
3524   char *comment = (parc > 2 && !BadPtr(parv[parc - 1])) ? parv[parc - 1] : NULL;
3525
3526   *pbuf = '\0';                 /* Initialize the part buffer... -Kev */
3527
3528   sptr->flags &= ~FLAGS_TS8;
3529
3530   if (parc < 2 || parv[1][0] == '\0')
3531   {
3532     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "PART");
3533     return 0;
3534   }
3535
3536   for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
3537   {
3538     chptr = get_channel(sptr, name, !CREATE);
3539     if (!chptr)
3540     {
3541       sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
3542       continue;
3543     }
3544     if (*name == '&' && !MyUser(sptr))
3545       continue;
3546     /* Do not use IsMember here: zombies must be able to part too */
3547     if (!(lp = find_user_link(chptr->members, sptr)))
3548     {
3549       /* Normal to get when our client did a kick
3550          for a remote client (who sends back a PART),
3551          so check for remote client or not --Run */
3552       if (MyUser(sptr))
3553         sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
3554             chptr->chname);
3555       continue;
3556     }
3557     /* Recreate the /part list for sending to servers */
3558     if (*name != '&')
3559     {
3560       if (*pbuf)
3561         strcat(pbuf, ",");
3562       strcat(pbuf, name);
3563     }
3564     if (can_send(sptr, chptr) != 0)     /* Returns 0 if we CAN send */
3565       comment = NULL;
3566     /* Send part to all clients */
3567     if (!(lp->flags & CHFL_ZOMBIE))
3568     {
3569       if (comment)
3570         sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], chptr->chname,
3571             comment);
3572       else
3573         sendto_channel_butserv(chptr, sptr, PartFmt1, parv[0], chptr->chname);
3574     }
3575     else if (MyUser(sptr))
3576     {
3577       if (comment)
3578         sendto_one(sptr, PartFmt2, parv[0], chptr->chname, comment);
3579       else
3580         sendto_one(sptr, PartFmt1, parv[0], chptr->chname);
3581     }
3582     remove_user_from_channel(sptr, chptr);
3583   }
3584   /* Send out the parts to all servers... -Kev */
3585   if (*pbuf)
3586   {
3587     if (comment)
3588       sendto_serv_butone(cptr, PartFmt2, parv[0], pbuf, comment);
3589     else
3590       sendto_serv_butone(cptr, PartFmt1, parv[0], pbuf);
3591   }
3592   return 0;
3593 }
3594
3595 /*
3596  * m_kick
3597  *
3598  * parv[0] = sender prefix
3599  * parv[1] = channel
3600  * parv[2] = client to kick
3601  * parv[parc-1] = kick comment
3602  */
3603 int m_kick(aClient *cptr, aClient *sptr, int parc, char *parv[])
3604 {
3605   aClient *who;
3606   aChannel *chptr;
3607   char *comment;
3608   Link *lp, *lp2;
3609
3610   sptr->flags &= ~FLAGS_TS8;
3611
3612   if (parc < 3 || *parv[1] == '\0')
3613   {
3614     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "KICK");
3615     return 0;
3616   }
3617
3618   if (IsServer(sptr))
3619     send_hack_notice(cptr, sptr, parc, parv, 1, 3);
3620
3621   comment = (BadPtr(parv[parc - 1])) ? parv[0] : parv[parc - 1];
3622   if (strlen(comment) > (size_t)TOPICLEN)
3623     comment[TOPICLEN] = '\0';
3624
3625   *nickbuf = *buf = '\0';
3626
3627   chptr = get_channel(sptr, parv[1], !CREATE);
3628   if (!chptr)
3629   {
3630     sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
3631     return 0;
3632   }
3633   if (IsLocalChannel(parv[1]) && !MyUser(sptr))
3634     return 0;
3635   if (IsModelessChannel(parv[1]))
3636   {
3637     sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
3638         chptr->chname);
3639     return 0;
3640   }
3641   if (!IsServer(cptr) && !is_chan_op(sptr, chptr))
3642   {
3643     sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3644         me.name, parv[0], chptr->chname);
3645     return 0;
3646   }
3647
3648   lp2 = find_user_link(chptr->members, sptr);
3649   if (MyUser(sptr) || Protocol(cptr) < 10)
3650   {
3651     if (!(who = find_chasing(sptr, parv[2], NULL)))
3652       return 0;                 /* No such user left! */
3653   }
3654   else if (!(who = findNUser(parv[2])))
3655     return 0;                   /* No such user left! */
3656   /* if the user is +k, prevent a kick from local user */
3657   if (IsChannelService(who) && MyUser(sptr))
3658   {
3659     sendto_one(sptr, err_str(ERR_ISCHANSERVICE), me.name,
3660         parv[0], who->name, chptr->chname);
3661     return 0;
3662   }
3663 #ifdef NO_OPER_DEOP_LCHAN
3664   /*
3665    * Prevent kicking opers from local channels -DM-
3666    */
3667   if (IsOperOnLocalChannel(who, chptr->chname))
3668   {
3669     sendto_one(sptr, err_str(ERR_ISOPERLCHAN), me.name,
3670                parv[0], who->name, chptr->chname);
3671     return 0;
3672   }
3673 #endif
3674
3675   if (((lp = find_user_link(chptr->members, who)) &&
3676       !(lp->flags & CHFL_ZOMBIE)) || IsServer(sptr))
3677   {
3678     if (who->from != cptr &&
3679         ((lp2 && (lp2->flags & CHFL_DEOPPED)) || (!lp2 && IsUser(sptr))))
3680     {
3681       /*
3682        * Bounce here:
3683        * cptr must be a server (or cptr == sptr and
3684        * sptr->flags can't have DEOPPED set
3685        * when CHANOP is set).
3686        */
3687       sendto_one(cptr, ":%s JOIN %s", who->name, parv[1]);
3688       if (lp->flags & CHFL_CHANOP)
3689       {
3690         if (Protocol(cptr) < 10)
3691           sendto_one(cptr, ":%s MODE %s +o %s " TIME_T_FMT,
3692               me.name, parv[1], who->name, chptr->creationtime);
3693         else
3694           sendto_one(cptr, "%s MODE %s +o %s%s " TIME_T_FMT,
3695               NumServ(&me), parv[1], NumNick(who), chptr->creationtime);
3696       }
3697       if (lp->flags & CHFL_VOICE)
3698       {
3699         if (Protocol(cptr) < 10)
3700           sendto_one(cptr, ":%s MODE %s +v %s " TIME_T_FMT,
3701               me.name, chptr->chname, who->name, chptr->creationtime);
3702         else
3703           sendto_one(cptr, "%s MODE %s +v %s%s " TIME_T_FMT,
3704               NumServ(&me), parv[1], NumNick(who), chptr->creationtime);
3705       }
3706     }
3707     else
3708     {
3709       if (lp)
3710         sendto_channel_butserv(chptr, sptr,
3711             ":%s KICK %s %s :%s", parv[0], chptr->chname, who->name, comment);
3712       if (!IsLocalChannel(parv[1]))
3713       {
3714         sendto_lowprot_butone(cptr, 9, ":%s KICK %s %s :%s",
3715             parv[0], chptr->chname, who->name, comment);
3716         sendto_highprot_butone(cptr, 10, ":%s KICK %s %s%s :%s",
3717             parv[0], parv[1], NumNick(who), comment);
3718       }
3719       if (lp)
3720       {
3721 /*
3722  * Consider:
3723  *
3724  *                     client
3725  *                       |
3726  *                       c
3727  *                       |
3728  *     X --a--> A --b--> B --d--> D
3729  *                       |
3730  *                      who
3731  *
3732  * Where `who' is being KICK-ed by a "KICK" message received by server 'A'
3733  * via 'a', or on server 'B' via either 'b' or 'c', or on server D via 'd'.
3734  *
3735  * a) On server A : set CHFL_ZOMBIE for `who' (lp) and pass on the KICK.
3736  *    Remove the user immedeately when no users are left on the channel.
3737  * b) On server B : remove the user (who/lp) from the channel, send a
3738  *    PART upstream (to A) and pass on the KICK.
3739  * c) KICKed by `client'; On server B : remove the user (who/lp) from the
3740  *    channel, and pass on the KICK.
3741  * d) On server D : remove the user (who/lp) from the channel, and pass on
3742  *    the KICK.
3743  *
3744  * Note:
3745  * - Setting the ZOMBIE flag never hurts, we either remove the
3746  *   client after that or we don't.
3747  * - The KICK message was already passed on, as should be in all cases.
3748  * - `who' is removed in all cases except case a) when users are left.
3749  * - A PART is only sent upstream in case b).
3750  *
3751  * 2 aug 97:
3752  *
3753  *              6
3754  *              |
3755  *  1 --- 2 --- 3 --- 4 --- 5
3756  *        |           |
3757  *      kicker       who
3758  *
3759  * We also need to turn 'who' into a zombie on servers 1 and 6,
3760  * because a KICK from 'who' (kicking someone else in that direction)
3761  * can arrive there afterwards - which should not be bounced itself.
3762  * Therefore case a) also applies for servers 1 and 6.
3763  *
3764  * --Run
3765  */
3766         /* Default for case a): */
3767         lp->flags |= CHFL_ZOMBIE;
3768         /* Case b) or c) ?: */
3769         if (MyUser(who))        /* server 4 */
3770         {
3771           if (IsServer(cptr))   /* Case b) ? */
3772             sendto_one(cptr, PartFmt1, who->name, parv[1]);
3773           remove_user_from_channel(who, chptr);
3774           return 0;
3775         }
3776         if (who->from == cptr)  /* True on servers 1, 5 and 6 */
3777         {
3778           aClient *acptr = IsServer(sptr) ? sptr : sptr->user->server;
3779           for (; acptr != &me; acptr = acptr->serv->up)
3780             if (acptr == who->user->server)     /* Case d) (server 5) */
3781             {
3782               remove_user_from_channel(who, chptr);
3783               return 0;
3784             }
3785         }
3786         /* Case a) (servers 1, 2, 3 and 6) */
3787         for (lp = chptr->members; lp; lp = lp->next)
3788           if (!(lp->flags & CHFL_ZOMBIE))
3789             break;
3790         if (!lp)
3791           remove_user_from_channel(who, chptr);
3792 #ifdef GODMODE
3793         else
3794           sendto_op_mask(SNO_HACK2, "%s is now a zombie on %s",
3795               who->name, chptr->chname);
3796 #endif
3797       }
3798     }
3799   }
3800   else if (MyUser(sptr))
3801     sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
3802         me.name, parv[0], who->name, chptr->chname);
3803
3804   return 0;
3805 }
3806
3807 /*
3808  * m_topic
3809  *
3810  * parv[0]        = sender prefix
3811  * parv[1]        = channel
3812  * parv[parc - 1] = topic (if parc > 2)
3813  */
3814 int m_topic(aClient *cptr, aClient *sptr, int parc, char *parv[])
3815 {
3816   aChannel *chptr;
3817   char *topic = NULL, *name, *p = NULL;
3818
3819   if (parc < 2)
3820   {
3821     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "TOPIC");
3822     return 0;
3823   }
3824
3825   if (parc > 2)
3826     topic = parv[parc - 1];
3827
3828   for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
3829   {
3830     chptr = NULL;
3831     if (!IsChannelName(name) || !(chptr = FindChannel(name)) ||
3832         ((topic || SecretChannel(chptr)) && !IsMember(sptr, chptr)))
3833     {
3834       sendto_one(sptr, err_str(chptr ? ERR_NOTONCHANNEL : ERR_NOSUCHCHANNEL),
3835           me.name, parv[0], chptr ? chptr->chname : name);
3836       continue;
3837     }
3838     if (IsModelessChannel(name))
3839     {
3840       sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
3841           chptr->chname);
3842       continue;
3843     }
3844     if (IsLocalChannel(name) && !MyUser(sptr))
3845       continue;
3846
3847     if (!topic)                 /* only asking  for topic  */
3848     {
3849       if (chptr->topic[0] == '\0')
3850         sendto_one(sptr, rpl_str(RPL_NOTOPIC), me.name, parv[0], chptr->chname);
3851       else
3852       {
3853         sendto_one(sptr, rpl_str(RPL_TOPIC),
3854             me.name, parv[0], chptr->chname, chptr->topic);
3855         sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME),
3856             me.name, parv[0], chptr->chname,
3857             chptr->topic_nick, chptr->topic_time);
3858       }
3859     }
3860     else if (((chptr->mode.mode & MODE_TOPICLIMIT) == 0 ||
3861         is_chan_op(sptr, chptr)) && topic)
3862     {
3863       /* setting a topic */
3864       strncpy(chptr->topic, topic, TOPICLEN);
3865       strncpy(chptr->topic_nick, sptr->name, NICKLEN);
3866       chptr->topic_time = now;
3867       sendto_serv_butone(cptr, ":%s TOPIC %s :%s",
3868           parv[0], chptr->chname, chptr->topic);
3869       sendto_channel_butserv(chptr, sptr, ":%s TOPIC %s :%s",
3870           parv[0], chptr->chname, chptr->topic);
3871     }
3872     else
3873       sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3874           me.name, parv[0], chptr->chname);
3875   }
3876   return 0;
3877 }
3878
3879 /*
3880  * m_invite
3881  *   parv[0] - sender prefix
3882  *   parv[1] - user to invite
3883  *   parv[2] - channel name
3884  *
3885  * - INVITE now is accepted only if who does it is chanop (this of course
3886  *   implies that channel must exist and he must be on it).
3887  *
3888  * - On the other side it IS processed even if channel is NOT invite only
3889  *   leaving room for other enhancements like inviting banned ppl.  -- Nemesi
3890  *
3891  */
3892 int m_invite(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
3893 {
3894   aClient *acptr;
3895   aChannel *chptr;
3896
3897   if (parc < 3 || *parv[2] == '\0')
3898   {
3899     sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "INVITE");
3900     return 0;
3901   }
3902
3903   if (!(acptr = FindUser(parv[1])))
3904   {
3905     sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
3906     return 0;
3907   }
3908
3909   if (is_silenced(sptr, acptr))
3910     return 0;
3911
3912   if (MyUser(sptr))
3913     clean_channelname(parv[2]);
3914   else if (IsLocalChannel(parv[2]))
3915     return 0;
3916
3917   if (*parv[2] == '0' || !IsChannelName(parv[2]))
3918     return 0;
3919
3920   if (!(chptr = FindChannel(parv[2])))
3921   {
3922     if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2]))
3923     {
3924       sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], parv[2]);
3925       return 0;
3926     }
3927
3928     /* Do not disallow to invite to non-existant #channels, otherwise they
3929        would simply first be created, causing only MORE bandwidth usage. */
3930     if (MyConnect(sptr))
3931     {
3932       if (check_target_limit(sptr, acptr, acptr->name, 0))
3933         return 0;
3934
3935       sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
3936           acptr->name, parv[2]);
3937
3938       if (acptr->user->away)
3939         sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
3940             acptr->name, acptr->user->away);
3941     }
3942
3943     sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
3944         acptr->name, parv[2]);
3945
3946     return 0;
3947   }
3948
3949   if (!IsMember(sptr, chptr))
3950   {
3951     sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
3952         chptr->chname);
3953     return 0;
3954   }
3955
3956   if (IsMember(acptr, chptr))
3957   {
3958     sendto_one(sptr, err_str(ERR_USERONCHANNEL),
3959         me.name, parv[0], acptr->name, chptr->chname);
3960     return 0;
3961   }
3962
3963   if (MyConnect(sptr))
3964   {
3965     if (!is_chan_op(sptr, chptr))
3966     {
3967       sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
3968           me.name, parv[0], chptr->chname);
3969       return 0;
3970     }
3971
3972     /* If we get here, it was a VALID and meaningful INVITE */
3973
3974     if (check_target_limit(sptr, acptr, acptr->name, 0))
3975       return 0;
3976
3977     sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0],
3978         acptr->name, chptr->chname);
3979
3980     if (acptr->user->away)
3981       sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0],
3982           acptr->name, acptr->user->away);
3983   }
3984
3985   if (MyConnect(acptr))
3986     add_invite(acptr, chptr);
3987
3988   sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
3989       acptr->name, chptr->chname);
3990
3991   return 0;
3992 }
3993
3994 static int number_of_zombies(aChannel *chptr)
3995 {
3996   Reg1 Link *lp;
3997   Reg2 int count = 0;
3998   for (lp = chptr->members; lp; lp = lp->next)
3999     if (lp->flags & CHFL_ZOMBIE)
4000       count++;
4001   return count;
4002 }
4003
4004 /*
4005  * m_list
4006  *
4007  * parv[0] = sender prefix
4008  * parv[1] = channel list or user/time limit
4009  * parv[2...] = more user/time limits
4010  */
4011 int m_list(aClient *UNUSED(cptr), aClient *sptr, int parc, char *parv[])
4012 {
4013   aChannel *chptr;
4014   char *name, *p = NULL;
4015   int show_usage = 0, show_channels = 0, param;
4016   aListingArgs args = {
4017     2147483647,                 /* max_time */
4018     0,                          /* min_time */
4019     4294967295U,                /* max_users */
4020     0,                          /* min_users */
4021     0,                          /* topic_limits */
4022     2147483647,                 /* max_topic_time */
4023     0,                          /* min_topic_time */
4024     NULL                        /* chptr */
4025   };
4026
4027   if (sptr->listing)            /* Already listing ? */
4028   {
4029     sptr->listing->chptr->mode.mode &= ~MODE_LISTED;
4030     RunFree(sptr->listing);
4031     sptr->listing = NULL;
4032     sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, sptr->name);
4033     if (parc < 2)
4034       return 0;                 /* Let LIST abort a listing. */
4035   }
4036
4037   if (parc < 2)                 /* No arguments given to /LIST ? */
4038   {
4039 #ifdef DEFAULT_LIST_PARAM
4040     static char *defparv[MAXPARA + 1];
4041     static int defparc = 0;
4042     static char lp[] = DEFAULT_LIST_PARAM;
4043     int i;
4044
4045     if (!defparc)
4046     {
4047       char *s = lp, *t;
4048
4049       defparc = 1;
4050       defparv[defparc++] = t = strtok(s, " ");
4051       while (t && defparc < MAXPARA)
4052       {
4053         if ((t = strtok(NULL, " ")))
4054           defparv[defparc++] = t;
4055       }
4056     }
4057     for (i = 1; i < defparc; i++)
4058       parv[i] = defparv[i];
4059     parv[i] = NULL;
4060     parc = defparc;
4061 #endif /* DEFAULT_LIST_PARAM */
4062   }
4063
4064   /* Decode command */
4065   for (param = 1; !show_usage && parv[param]; param++)
4066   {
4067     char *p = parv[param];
4068     do
4069     {
4070       int is_time = 0;
4071       switch (*p)
4072       {
4073         case 'T':
4074         case 't':
4075           is_time++;
4076           args.topic_limits = 1;
4077           /* Fall through */
4078         case 'C':
4079         case 'c':
4080           is_time++;
4081           p++;
4082           if (*p != '<' && *p != '>')
4083           {
4084             show_usage = 1;
4085             break;
4086           }
4087           /* Fall through */
4088         case '<':
4089         case '>':
4090         {
4091           p++;
4092           if (!isDigit(*p))
4093             show_usage = 1;
4094           else
4095           {
4096             if (is_time)
4097             {
4098               time_t val = atoi(p);
4099               if (p[-1] == '<')
4100               {
4101                 if (val < 80000000)     /* Toggle UTC/offset */
4102                 {
4103                   /*
4104                    * Demands that
4105                    * 'TStime() - chptr->creationtime < val * 60'
4106                    * Which equals
4107                    * 'chptr->creationtime > TStime() - val * 60'
4108                    */
4109                   if (is_time == 1)
4110                     args.min_time = TStime() - val * 60;
4111                   else
4112                     args.min_topic_time = TStime() - val * 60;
4113                 }
4114                 else if (is_time == 1)  /* Creation time in UTC was entered */
4115                   args.max_time = val;
4116                 else            /* Topic time in UTC was entered */
4117                   args.max_topic_time = val;
4118               }
4119               else if (val < 80000000)
4120               {
4121                 if (is_time == 1)
4122                   args.max_time = TStime() - val * 60;
4123                 else
4124                   args.max_topic_time = TStime() - val * 60;
4125               }
4126               else if (is_time == 1)
4127                 args.min_time = val;
4128               else
4129                 args.min_topic_time = val;
4130             }
4131             else if (p[-1] == '<')
4132               args.max_users = atoi(p);
4133             else
4134               args.min_users = atoi(p);
4135             if ((p = strchr(p, ',')))
4136               p++;
4137           }
4138           break;
4139         }
4140         default:
4141           if (!IsChannelName(p))
4142           {
4143             show_usage = 1;
4144             break;
4145           }
4146           if (parc != 2)        /* Don't allow a mixture of channels with <,> */
4147             show_usage = 1;
4148           show_channels = 1;
4149           p = NULL;
4150           break;
4151       }
4152     }
4153     while (!show_usage && p);   /* p points after comma, or is NULL */
4154   }
4155
4156   if (show_usage)
4157   {
4158     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4159         "Usage: \002/QUOTE LIST\002 \037parameters\037");
4160     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4161         "Where \037parameters\037 is a space or comma seperated "
4162         "list of one or more of:");
4163     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4164         " \002<\002\037max_users\037    ; Show all channels with less "
4165         "than \037max_users\037.");
4166     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4167         " \002>\002\037min_users\037    ; Show all channels with more "
4168         "than \037min_users\037.");
4169     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4170         " \002C<\002\037max_minutes\037 ; Channels that exist less "
4171         "than \037max_minutes\037.");
4172     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4173         " \002C>\002\037min_minutes\037 ; Channels that exist more "
4174         "than \037min_minutes\037.");
4175     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4176         " \002T<\002\037max_minutes\037 ; Channels with a topic last "
4177         "set less than \037max_minutes\037 ago.");
4178     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4179         " \002T>\002\037min_minutes\037 ; Channels with a topic last "
4180         "set more than \037min_minutes\037 ago.");
4181     sendto_one(sptr, rpl_str(RPL_LISTUSAGE), me.name, parv[0],
4182         "Example: LIST <3,>1,C<10,T>0  ; 2 users, younger than 10 min., "
4183         "topic set.");
4184     return 0;
4185   }
4186
4187   sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, parv[0]);
4188
4189   if (!show_channels)
4190   {
4191     if (args.max_users > args.min_users + 1 && args.max_time > args.min_time &&
4192         args.max_topic_time > args.min_topic_time)      /* Sanity check */
4193     {
4194       if ((sptr->listing = (aListingArgs *)RunMalloc(sizeof(aListingArgs))))
4195       {
4196         memcpy(sptr->listing, &args, sizeof(aListingArgs));
4197         if ((sptr->listing->chptr = channel))
4198         {
4199           int m = channel->mode.mode & MODE_LISTED;
4200           list_next_channels(sptr, 64);
4201           channel->mode.mode |= m;
4202           return 0;
4203         }
4204         RunFree(sptr->listing);
4205         sptr->listing = NULL;
4206       }
4207     }
4208     sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
4209     return 0;
4210   }
4211
4212   for (; (name = strtoken(&p, parv[1], ",")); parv[1] = NULL)
4213   {
4214     chptr = FindChannel(name);
4215     if (chptr && ShowChannel(sptr, chptr) && sptr->user)
4216       sendto_one(sptr, rpl_str(RPL_LIST), me.name, parv[0],
4217           ShowChannel(sptr, chptr) ? chptr->chname : "*",
4218           chptr->users - number_of_zombies(chptr), chptr->topic);
4219   }
4220
4221   sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
4222   return 0;
4223 }
4224
4225 /*
4226  * m_names                              - Added by Jto 27 Apr 1989
4227  *
4228  * parv[0] = sender prefix
4229  * parv[1] = channel
4230  */
4231 int m_names(aClient *cptr, aClient *sptr, int parc, char *parv[])
4232 {
4233   Reg1 aChannel *chptr;
4234   Reg2 aClient *c2ptr;
4235   Reg3 Link *lp;
4236   aChannel *ch2ptr = NULL;
4237   int idx, flag, len, mlen;
4238   char *s, *para = parc > 1 ? parv[1] : NULL;
4239
4240   if (parc > 2 && hunt_server(1, cptr, sptr, ":%s NAMES %s %s", 2, parc, parv))
4241     return 0;
4242
4243   mlen = strlen(me.name) + 10 + strlen(sptr->name);
4244
4245   if (!BadPtr(para))
4246   {
4247     s = strchr(para, ',');
4248     if (s)
4249     {
4250       parv[1] = ++s;
4251       m_names(cptr, sptr, parc, parv);
4252     }
4253     clean_channelname(para);
4254     ch2ptr = FindChannel(para);
4255   }
4256
4257   /*
4258    * First, do all visible channels (public and the one user self is)
4259    */
4260
4261   for (chptr = channel; chptr; chptr = chptr->nextch)
4262   {
4263     if ((chptr != ch2ptr) && !BadPtr(para))
4264       continue;                 /* -- wanted a specific channel */
4265     if (!MyConnect(sptr) && BadPtr(para))
4266       continue;
4267 #ifndef GODMODE
4268     if (!ShowChannel(sptr, chptr))
4269       continue;                 /* -- users on this are not listed */
4270 #endif
4271
4272     /* Find users on same channel (defined by chptr) */
4273
4274     strcpy(buf, "* ");
4275     len = strlen(chptr->chname);
4276     strcpy(buf + 2, chptr->chname);
4277     strcpy(buf + 2 + len, " :");
4278
4279     if (PubChannel(chptr))
4280       *buf = '=';
4281     else if (SecretChannel(chptr))
4282       *buf = '@';
4283     idx = len + 4;
4284     flag = 1;
4285     for (lp = chptr->members; lp; lp = lp->next)
4286     {
4287       c2ptr = lp->value.cptr;
4288 #ifndef GODMODE
4289       if (sptr != c2ptr && IsInvisible(c2ptr) && !IsMember(sptr, chptr))
4290         continue;
4291 #endif
4292       if (lp->flags & CHFL_ZOMBIE)
4293       {
4294         if (lp->value.cptr != sptr)
4295           continue;
4296         else
4297         {
4298           strcat(buf, "!");
4299           idx++;
4300         }
4301       }
4302       else if (lp->flags & CHFL_CHANOP)
4303       {
4304         strcat(buf, "@");
4305         idx++;
4306       }
4307       else if (lp->flags & CHFL_VOICE)
4308       {
4309         strcat(buf, "+");
4310         idx++;
4311       }
4312       strcat(buf, c2ptr->name);
4313       strcat(buf, " ");
4314       idx += strlen(c2ptr->name) + 1;
4315       flag = 1;
4316 #ifdef GODMODE
4317       {
4318         char yxx[6];
4319         sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
4320         if (c2ptr != findNUser(yxx))
4321           MyCoreDump;
4322         sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
4323         idx += 6;
4324       }
4325       if (mlen + idx + NICKLEN + 11 > BUFSIZE)
4326 #else
4327       if (mlen + idx + NICKLEN + 5 > BUFSIZE)
4328 #endif
4329         /* space, modifier, nick, \r \n \0 */
4330       {
4331         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4332         strcpy(buf, "* ");
4333         strncpy(buf + 2, chptr->chname, len + 1);
4334         buf[len + 2] = 0;
4335         strcat(buf, " :");
4336         if (PubChannel(chptr))
4337           *buf = '=';
4338         else if (SecretChannel(chptr))
4339           *buf = '@';
4340         idx = len + 4;
4341         flag = 0;
4342       }
4343     }
4344     if (flag)
4345       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4346   }
4347   if (!BadPtr(para))
4348   {
4349     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0],
4350         ch2ptr ? ch2ptr->chname : para);
4351     return (1);
4352   }
4353
4354   /* Second, do all non-public, non-secret channels in one big sweep */
4355
4356   strcpy(buf, "* * :");
4357   idx = 5;
4358   flag = 0;
4359   for (c2ptr = client; c2ptr; c2ptr = c2ptr->next)
4360   {
4361     aChannel *ch3ptr;
4362     int showflag = 0, secret = 0;
4363
4364 #ifndef GODMODE
4365     if (!IsUser(c2ptr) || (sptr != c2ptr && IsInvisible(c2ptr)))
4366 #else
4367     if (!IsUser(c2ptr))
4368 #endif
4369       continue;
4370     lp = c2ptr->user->channel;
4371     /*
4372      * Don't show a client if they are on a secret channel or when
4373      * they are on a channel sptr is on since they have already
4374      * been show earlier. -avalon
4375      */
4376     while (lp)
4377     {
4378       ch3ptr = lp->value.chptr;
4379 #ifndef GODMODE
4380       if (PubChannel(ch3ptr) || IsMember(sptr, ch3ptr))
4381 #endif
4382         showflag = 1;
4383       if (SecretChannel(ch3ptr))
4384         secret = 1;
4385       lp = lp->next;
4386     }
4387     if (showflag)               /* Have we already shown them ? */
4388       continue;
4389 #ifndef GODMODE
4390     if (secret)                 /* On any secret channels ? */
4391       continue;
4392 #endif
4393     strcat(buf, c2ptr->name);
4394     strcat(buf, " ");
4395     idx += strlen(c2ptr->name) + 1;
4396     flag = 1;
4397 #ifdef GODMODE
4398     {
4399       char yxx[6];
4400       sprintf_irc(yxx, "%s%s", NumNick(c2ptr));
4401       if (c2ptr != findNUser(yxx))
4402         MyCoreDump;
4403       sprintf_irc(buf + strlen(buf), "(%s) ", yxx);
4404       idx += 6;
4405     }
4406 #endif
4407 #ifdef GODMODE
4408     if (mlen + idx + NICKLEN + 9 > BUFSIZE)
4409 #else
4410     if (mlen + idx + NICKLEN + 3 > BUFSIZE)     /* space, \r\n\0 */
4411 #endif
4412     {
4413       sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4414       strcpy(buf, "* * :");
4415       idx = 5;
4416       flag = 0;
4417     }
4418   }
4419   if (flag)
4420     sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
4421   sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
4422   return (1);
4423 }
4424
4425 void send_user_joins(aClient *cptr, aClient *user)
4426 {
4427   Reg1 Link *lp;
4428   Reg2 aChannel *chptr;
4429   Reg3 int cnt = 0, len = 0, clen;
4430   char *mask;
4431
4432   *buf = ':';
4433   strcpy(buf + 1, user->name);
4434   strcat(buf, " JOIN ");
4435   len = strlen(user->name) + 7;
4436
4437   for (lp = user->user->channel; lp; lp = lp->next)
4438   {
4439     chptr = lp->value.chptr;
4440     if ((mask = strchr(chptr->chname, ':')))
4441       if (match(++mask, cptr->name))
4442         continue;
4443     if (*chptr->chname == '&')
4444       continue;
4445     if (is_zombie(user, chptr))
4446       continue;
4447     clen = strlen(chptr->chname);
4448     if (clen + 1 + len > BUFSIZE - 3)
4449     {
4450       if (cnt)
4451       {
4452         buf[len - 1] = '\0';
4453         sendto_one(cptr, "%s", buf);
4454       }
4455       *buf = ':';
4456       strcpy(buf + 1, user->name);
4457       strcat(buf, " JOIN ");
4458       len = strlen(user->name) + 7;
4459       cnt = 0;
4460     }
4461     strcpy(buf + len, chptr->chname);
4462     cnt++;
4463     len += clen;
4464     if (lp->next)
4465     {
4466       len++;
4467       strcat(buf, ",");
4468     }
4469   }
4470   if (*buf && cnt)
4471     sendto_one(cptr, "%s", buf);
4472
4473   return;
4474 }
4475
4476 /*
4477  * send_hack_notice()
4478  *
4479  * parc & parv[] are the same as that of the calling function:
4480  *   mtype == 1 is from m_mode, 2 is from m_create, 3 is from m_kick.
4481  *
4482  * This function prepares sendbuf with the server notices and wallops
4483  *   to be sent for all hacks.  -Ghostwolf 18-May-97
4484  */
4485
4486 static void send_hack_notice(aClient *cptr, aClient *sptr, int parc,
4487     char *parv[], int badop, int mtype)
4488 {
4489   aChannel *chptr;
4490   static char params[MODEBUFLEN];
4491   int i = 3;
4492   chptr = FindChannel(parv[1]);
4493   *params = '\0';
4494
4495   if (Protocol(cptr) < 10)      /* We don't get numeric nicks from P09  */
4496   {                             /* servers, so this can be sent "As Is" */
4497     if (mtype == 1)
4498     {
4499       while (i < parc)
4500       {
4501         strcat(params, " ");
4502         strcat(params, parv[i++]);
4503       }
4504       sprintf_irc(sendbuf,
4505           ":%s NOTICE * :*** Notice -- %sHACK(%d): %s MODE %s %s%s [" TIME_T_FMT
4506           "]", me.name, (badop == 3) ? "BOUNCE or " : "", badop, parv[0],
4507           parv[1], parv[2], params, chptr->creationtime);
4508       sendbufto_op_mask((badop == 3) ? SNO_HACK3 : (badop ==
4509           4) ? SNO_HACK4 : SNO_HACK2);
4510
4511       if ((IsServer(sptr)) && (badop == 2))
4512       {
4513         sprintf_irc(sendbuf, ":%s DESYNCH :HACK: %s MODE %s %s%s",
4514             me.name, parv[0], parv[1], parv[2], params);
4515         sendbufto_serv_butone(cptr);
4516       }
4517     }
4518     else if (mtype == 3)
4519     {
4520       sprintf_irc(sendbuf,
4521           ":%s NOTICE * :*** Notice -- HACK: %s KICK %s %s :%s",
4522           me.name, sptr->name, parv[1], parv[2], parv[3]);
4523       sendbufto_op_mask(SNO_HACK4);
4524     }
4525   }
4526   else
4527   {
4528     /* P10 servers require numeric nick conversion before sending. */
4529     switch (mtype)
4530     {
4531       case 1:                   /* Convert nicks for MODE HACKs here  */
4532       {
4533         char *mode = parv[2];
4534         while (i < parc)
4535         {
4536           while (*mode && *mode != 'o' && *mode != 'v')
4537             ++mode;
4538           strcat(params, " ");
4539           if (*mode == 'o' || *mode == 'v')
4540           {
4541             register aClient *acptr;
4542             if ((acptr = findNUser(parv[i])) != NULL)   /* Convert nicks here */
4543               strcat(params, acptr->name);
4544             else
4545             {
4546               strcat(params, "<");
4547               strcat(params, parv[i]);
4548               strcat(params, ">");
4549             }
4550           }
4551           else                  /* If it isn't a numnick, send it 'as is' */
4552             strcat(params, parv[i]);
4553           i++;
4554         }
4555         sprintf_irc(sendbuf,
4556             ":%s NOTICE * :*** Notice -- %sHACK(%d): %s MODE %s %s%s ["
4557             TIME_T_FMT "]", me.name, (badop == 3) ? "BOUNCE or " : "", badop,
4558             parv[0], parv[1], parv[2], params, chptr->creationtime);
4559         sendbufto_op_mask((badop == 3) ? SNO_HACK3 : (badop ==
4560             4) ? SNO_HACK4 : SNO_HACK2);
4561
4562         if ((IsServer(sptr)) && (badop == 2))
4563         {
4564           sprintf_irc(sendbuf, ":%s DESYNCH :HACK: %s MODE %s %s%s",
4565               me.name, parv[0], parv[1], parv[2], params);
4566           sendbufto_serv_butone(cptr);
4567         }
4568         break;
4569       }
4570       case 2:                   /* No conversion is needed for CREATE; the only numnick is sptr */
4571       {
4572         sendto_serv_butone(cptr, ":%s DESYNCH :HACK: %s CREATE %s %s",
4573             me.name, sptr->name, chptr->chname, parv[2]);
4574         sendto_op_mask(SNO_HACK2, "HACK(2): %s CREATE %s %s",
4575             sptr->name, chptr->chname, parv[2]);
4576         break;
4577       }
4578       case 3:                   /* Convert nick in KICK message */
4579       {
4580         aClient *acptr;
4581         if ((acptr = findNUser(parv[2])) != NULL)       /* attempt to convert nick */
4582           sprintf_irc(sendbuf,
4583               ":%s NOTICE * :*** Notice -- HACK: %s KICK %s %s :%s",
4584               me.name, sptr->name, parv[1], acptr->name, parv[3]);
4585         else                    /* if conversion fails, send it 'as is' in <>'s */
4586           sprintf_irc(sendbuf,
4587               ":%s NOTICE * :*** Notice -- HACK: %s KICK %s <%s> :%s",
4588               me.name, sptr->name, parv[1], parv[2], parv[3]);
4589         sendbufto_op_mask(SNO_HACK4);
4590         break;
4591       }
4592     }
4593   }
4594 }