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