"Fossies" - the Fresh Open Source Software Archive

Member "bahamut-2.1.5/src/channel.c" (28 May 2020, 175791 Bytes) of package /linux/privat/bahamut-2.1.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "channel.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.1.4_vs_2.1.5.

    1 /*
    2  *   IRC - Internet Relay Chat, src/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 "struct.h"
   22 #include "common.h"
   23 #include "sys.h"
   24 #include "numeric.h"
   25 #include "channel.h"
   26 #include "h.h"
   27 #include "userban.h"
   28 #include "memcount.h"
   29 #include "hooks.h"
   30 #include "spamfilter.h"
   31 
   32 int         server_was_split = YES;
   33 
   34 aChannel   *channel = NullChn;
   35 
   36 #ifdef USER_HOSTMASKING
   37 #define GET_USER_HOST(cptr) IsUmodeH(cptr)?cptr->user->mhost:cptr->user->host
   38 #else
   39 #define GET_USER_HOST(cptr) cptr->user->host
   40 #endif
   41 
   42 #ifdef INVITE_LISTS
   43 /* +I list functions */
   44 int       add_invite_id(aClient*, aChannel*, char*);
   45 int       del_invite_id(aChannel*, char*);
   46 anInvite* is_invited(aClient*, aChannel*);
   47 #endif
   48 
   49 #ifdef EXEMPT_LISTS
   50 /* +e list functions */
   51 int       add_exempt_id(aClient*, aChannel*, char*);
   52 int       del_exempt_id(aChannel*, char*);
   53 #endif
   54 
   55 static int  add_banid(aClient *, aChannel *, char *);
   56 static int  can_join(aClient *, aChannel *, char *);
   57 static void channel_modes(aClient *, char *, char *, aChannel *);
   58 static int  del_banid(aChannel *, char *);
   59 static int  is_banned(aClient *, aChannel *, chanMember *);
   60 static int  set_mode(aClient *, aClient *, aChannel *, int, 
   61                      int, char **, char *, char *);
   62 static void sub1_from_channel(aChannel *);
   63 
   64 int         check_channelname(aClient *, unsigned char *);
   65 void        clean_channelname(unsigned char *);
   66 static void add_invite(aClient *, aChannel *);
   67 void        del_invite(aClient *, aChannel *);
   68 
   69 #ifdef ORATIMING
   70 struct timeval tsdnow, tsdthen;
   71 unsigned long tsdms;
   72 #endif
   73 
   74 /* number of seconds to add to all readings of time() when making TS's */
   75 
   76 static char *PartFmt = ":%s PART %s";
   77 static char *PartFmt2 = ":%s PART %s :%s";
   78 
   79 /* server <-> server SJOIN format  */
   80 static char *SJOINFmt = ":%s SJOIN %ld %s %s %s :%s";
   81 /* NP means no paramaters, don't send the extra space there */
   82 static char *SJOINFmtNP = ":%s SJOIN %ld %s %s :%s";
   83 /* client SJOIN format, for no channel creation */
   84 static char *CliSJOINFmt = ":%s SJOIN %ld %s";
   85 
   86 /* some buffers for rebuilding channel/nick lists with ,'s */
   87 static char nickbuf[BUFSIZE], buf[BUFSIZE];
   88 static char modebuf[REALMODEBUFLEN], parabuf[REALMODEBUFLEN];
   89 
   90 /* externally defined function */
   91 extern Link *find_channel_link(Link *, aChannel *);     /* defined in list.c */
   92 extern int is_silenced(aClient *sptr, aClient *acptr); /* defined in s_user.c */
   93 extern struct FlagList xflags_list[]; /* for send_topic_burst() */
   94 extern int services_jr; /* for m_join() */
   95 #ifdef ANTI_SPAMBOT
   96 extern int  spam_num;           /* defined in s_serv.c */
   97 extern int  spam_time;          /* defined in s_serv.c */
   98 #endif
   99 
  100 /* return the length (>=0) of a chain of links. */
  101 static int list_length(Link *lp)
  102 {
  103     int     count = 0;
  104     
  105     for (; lp; lp = lp->next)
  106         count++;
  107     return count;
  108 }
  109 
  110 /* check to see if the message has any control chars in it. */
  111 static int
  112 msg_has_ctrls(char *msg)
  113 {
  114     unsigned char *c;
  115 
  116     if (msg == NULL)
  117         return 0;
  118 
  119     for (c = (unsigned char *)msg; *c; c++)
  120     {
  121         /* not a control code */
  122         if (*c > 31)
  123             continue;
  124 
  125         /* ctcp */
  126         if (*c == 1)
  127             continue;
  128 
  129         /* escape */
  130         if (*c == 27)
  131         {
  132             /* ISO 2022 charset shift sequence */
  133             if (c[1] == '$' || c[1] == '(')
  134             {
  135                 c++;
  136                 continue;
  137             }
  138         }
  139 
  140         /* control code */
  141         break;
  142     }
  143     if(*c)
  144         return 1;
  145     return 0;
  146 }
  147 
  148 /*
  149  * find_chasing 
  150  *   Find the client structure for a nick name (user) using history 
  151  *   mechanism if necessary. If the client is not found, an error message 
  152  *   (NO SUCH NICK) is generated. If the client was found through the 
  153  *   history, chasing will be 1 and otherwise 0.
  154  */
  155 aClient *find_chasing(aClient *sptr, char *user, int *chasing)
  156 {
  157     aClient *who = find_client(user, (aClient *) NULL);
  158     
  159     if (chasing)
  160         *chasing = 0;
  161     if (who)
  162         return who;
  163     if (!(who = get_history(user, (long) KILLCHASETIMELIMIT)))
  164     {
  165         sendto_one(sptr, err_str(ERR_NOSUCHNICK),
  166                    me.name, sptr->name, user);
  167         return ((aClient *) NULL);
  168     }
  169     if (chasing)
  170         *chasing = 1;
  171     return who;
  172 }
  173 
  174 /*
  175  * Fixes a string so that the first white space found becomes an end of
  176  * string marker (`\-`).  returns the 'fixed' string or "*" if the
  177  * string was NULL length or a NULL pointer.
  178  */
  179 static char * check_string(char *s)
  180 {
  181     static char star[2] = "*";
  182     char       *str = s;
  183     
  184     if (BadPtr(s))
  185         return star;
  186     
  187     for (; *s; s++)
  188         if (IsSpace(*s))
  189         {
  190             *s = '\0';
  191             break;
  192         }
  193     
  194     return (BadPtr(str)) ? star : str;
  195 }
  196 /*
  197  * create a string of form "foo!bar@fubar" given foo, bar and fubar as
  198  * the parameters.  If NULL, they become "*".
  199  */
  200 static char *make_nick_user_host(char *nick, char *name, char *host)
  201 {
  202     static char namebuf[NICKLEN + USERLEN + HOSTLEN + 6];
  203     int         n;
  204     char   *ptr1, *ptr2;
  205     
  206     ptr1 = namebuf;
  207     for (ptr2 = check_string(nick), n = NICKLEN; *ptr2 && n--;)
  208         *ptr1++ = *ptr2++;
  209     *ptr1++ = '!';
  210     for (ptr2 = check_string(name), n = USERLEN; *ptr2 && n--;)
  211         *ptr1++ = *ptr2++;
  212     *ptr1++ = '@';
  213     for (ptr2 = check_string(host), n = HOSTLEN; *ptr2 && n--;)
  214         *ptr1++ = *ptr2++;
  215     *ptr1 = '\0';
  216     return (namebuf);
  217 }
  218 
  219 /* Determine whether a client matches a CIDR banstr. */
  220 static int client_matches_cidrstr(aClient *cptr, char *banstr)
  221 {
  222     char cidrbuf[NICKLEN + USERLEN + HOSTLEN + 6];
  223     char ipbuf[16];
  224     char *s;
  225     int bits;
  226 
  227     if (!strchr(banstr, '/'))
  228     return 0;
  229 
  230     s = strchr(banstr, '@');
  231     if (s)
  232     s++;
  233     else
  234     return 0;
  235 
  236     bits = inet_parse_cidr(cptr->ip_family, s, ipbuf, sizeof(ipbuf));
  237     if (bits > 0 && bitncmp(&cptr->ip, ipbuf, bits) == 0)
  238     {
  239     /* Check the wildcards in the rest of the string. */
  240     snprintf(cidrbuf, sizeof(cidrbuf), "%s!%s@%s",
  241          check_string(cptr->name),
  242          check_string(cptr->user->username),
  243          s);
  244     if (match(banstr, cidrbuf) == 0)
  245         return 1;
  246     }
  247     return 0;
  248 }
  249 
  250 #ifdef EXEMPT_LISTS
  251 /* Exempt list functions (+e) */
  252 
  253 int add_exempt_id(aClient* cptr, aChannel* chptr, char* exempt_id)
  254 {
  255     aBanExempt*   exempt = NULL;
  256     int           cnt = 0;
  257 
  258     for (exempt = chptr->banexempt_list; exempt; exempt = exempt->next)
  259     {
  260         if (MyClient(cptr))
  261         {
  262             if (++cnt >= MAXEXEMPTLIST)
  263             {
  264                 sendto_one(cptr, getreply(ERR_BANLISTFULL), me.name, cptr->name,
  265                     chptr->chname, exempt_id, "exempt");
  266                 return -1;
  267             }
  268             if (!match(exempt->banstr, exempt_id))
  269                 return -1;
  270         }
  271         else if (!mycmp(exempt->banstr, exempt_id))
  272             return -1;
  273     }
  274     exempt = (aBanExempt*)MyMalloc(sizeof(aBanExempt));
  275     exempt->banstr = (char*)MyMalloc(strlen(exempt_id)+1);
  276     strcpy(exempt->banstr, exempt_id);
  277     exempt->when = timeofday;
  278     exempt->next = chptr->banexempt_list;
  279     chptr->banexempt_list = exempt;
  280     chptr->banserial++;
  281 
  282     if (IsPerson(cptr))
  283     {
  284         exempt->who = (char *) MyMalloc(strlen(cptr->name) +
  285                                      strlen(cptr->user->username) +
  286                                      strlen(GET_USER_HOST(cptr)) + 3);
  287         (void) ircsprintf(exempt->who, "%s!%s@%s",
  288                           cptr->name, cptr->user->username, GET_USER_HOST(cptr));
  289     }
  290     else
  291     {
  292         exempt->who = (char *) MyMalloc(strlen(cptr->name) + 1);
  293         (void) strcpy(exempt->who, cptr->name);
  294     }
  295 
  296     /* determine type for less matching later */
  297     if(exempt_id[0] == '*' && exempt_id[1] == '!')
  298     {
  299         if(exempt_id[2] == '*' && exempt_id[3] == '@')
  300             exempt->type = MTYP_HOST;
  301         else
  302             exempt->type = MTYP_USERHOST;
  303     }
  304     else
  305         exempt->type = MTYP_FULL;
  306 
  307     return 0;
  308 }
  309 
  310 int del_exempt_id(aChannel* chptr, char* exempt_id)
  311 {
  312    aBanExempt**  exempt;
  313    aBanExempt*   tmp;
  314 
  315    if (!exempt_id)
  316        return -1;
  317    for (exempt = &chptr->banexempt_list; *exempt; exempt = &((*exempt)->next))
  318    {
  319        if (mycmp(exempt_id, (*exempt)->banstr) == 0)
  320        {
  321            tmp = *exempt;
  322            *exempt = tmp->next;
  323 
  324            chptr->banserial++;
  325 
  326            MyFree(tmp->banstr);
  327            MyFree(tmp->who);
  328            MyFree(tmp);
  329            
  330            break;
  331        }
  332    }
  333    return 0;
  334 }
  335 
  336 #endif
  337 
  338 #ifdef INVITE_LISTS
  339 /* Invite list functions (+I) */
  340 
  341 int add_invite_id(aClient* cptr, aChannel* chptr, char* invite_id)
  342 {
  343     anInvite*     invite;
  344     int           cnt = 0;
  345     
  346     for (invite = chptr->invite_list; invite; invite = invite->next)
  347     {
  348         if (MyClient(cptr))
  349         {
  350             if (++cnt >= chptr->max_invites)
  351             {
  352                 sendto_one(cptr, getreply(ERR_BANLISTFULL), me.name, cptr->name,
  353                     chptr->chname, invite_id, "invite");
  354                 return -1;
  355             }
  356             if (!match(invite->invstr, invite_id))
  357                 return -1;
  358         }
  359         else if (!mycmp(invite->invstr, invite_id))
  360             return -1;
  361     }
  362 
  363     invite = (anInvite*)MyMalloc(sizeof(anInvite));
  364     invite->invstr = (char*)MyMalloc(strlen(invite_id)+1);
  365     strcpy(invite->invstr, invite_id);
  366     invite->when = timeofday;
  367     invite->next = chptr->invite_list;
  368     chptr->invite_list = invite;
  369     
  370     if (IsPerson(cptr))
  371     {
  372         invite->who = (char *) MyMalloc(strlen(cptr->name) +
  373                                      strlen(cptr->user->username) +
  374                                      strlen(GET_USER_HOST(cptr)) + 3);
  375         (void) ircsprintf(invite->who, "%s!%s@%s",
  376                           cptr->name, cptr->user->username, GET_USER_HOST(cptr));
  377     }
  378     else
  379     {
  380         invite->who = (char *) MyMalloc(strlen(cptr->name) + 1);
  381         (void) strcpy(invite->who, cptr->name);
  382     }
  383     return 0;
  384 }
  385 
  386 int del_invite_id(aChannel* chptr, char* invite_id)
  387 {
  388    anInvite**    invite;
  389    anInvite*     tmp;
  390 
  391    if (!invite_id)
  392        return -1;
  393    for (invite = &chptr->invite_list; *invite; invite = &((*invite)->next))
  394    {
  395        if (mycmp(invite_id, (*invite)->invstr) == 0)
  396        {
  397            tmp = *invite;
  398            *invite = tmp->next;
  399            
  400            MyFree(tmp->invstr);
  401            MyFree(tmp->who);
  402            MyFree(tmp);
  403            
  404            break;
  405        }
  406    }
  407    return 0;
  408 }
  409 
  410 anInvite* is_invited(aClient* cptr, aChannel* chptr)
  411 {
  412     char         s[NICKLEN + USERLEN + HOSTLEN + 6];
  413 #ifdef USER_HOSTMASKING
  414     char         s3[NICKLEN + USERLEN + HOSTLEN + 6];
  415 #endif
  416     char        *s2;
  417     anInvite*    invite;
  418 
  419     strcpy(s, make_nick_user_host(cptr->name, cptr->user->username,
  420                                   cptr->user->host));
  421 #ifdef USER_HOSTMASKING
  422     strcpy(s3, make_nick_user_host(cptr->name, cptr->user->username,
  423                                    cptr->user->mhost));
  424 #endif
  425     s2 = make_nick_user_host(cptr->name, cptr->user->username,
  426                              cptr->hostip);
  427 
  428     for (invite = chptr->invite_list; invite; invite = invite->next)
  429     {
  430         if (!match(invite->invstr, s) || !match(invite->invstr, s2) ||
  431 #ifdef USER_HOSTMASKING
  432             !match(invite->invstr, s3) ||
  433 #endif
  434         client_matches_cidrstr(cptr, invite->invstr))
  435             break;
  436     }
  437     return invite;
  438 }
  439 
  440 #endif
  441 
  442 /* Ban functions to work with mode +b */
  443 /* add_banid - add an id to be banned to the channel  (belongs to cptr) */
  444 
  445 static int add_banid(aClient *cptr, aChannel *chptr, char *banid)
  446 {
  447     aBan        *ban;
  448     int          cnt = 0;
  449     
  450     for (ban = chptr->banlist; ban; ban = ban->next)
  451     {
  452         /* Begin unbreaking redundant ban checking.  First step is to allow
  453          * ALL non-duplicates from remote servers.  Local clients are still
  454          * subject to the flawed redundancy check for compatibility with
  455          * older servers.  This check can be corrected later.  -Quension */
  456         if (MyClient(cptr))
  457         {
  458             if (++cnt >= chptr->max_bans)
  459             {
  460                 sendto_one(cptr, getreply(ERR_BANLISTFULL), me.name, cptr->name,
  461                         chptr->chname, banid, "ban");
  462                 return -1;
  463             }
  464             if (!match(ban->banstr, banid))
  465                 return -1;
  466         }
  467         else if (!mycmp(ban->banstr, banid))
  468             return -1;
  469     }
  470 
  471     ban = (aBan *) MyMalloc(sizeof(aBan));
  472     ban->banstr = (char *) MyMalloc(strlen(banid) + 1);
  473     (void) strcpy(ban->banstr, banid);
  474     ban->next = chptr->banlist;
  475     
  476     if (IsPerson(cptr))
  477     {
  478         ban->who = (char *) MyMalloc(strlen(cptr->name) +
  479                                      strlen(cptr->user->username) +
  480                                      strlen(GET_USER_HOST(cptr)) + 3);
  481         (void) ircsprintf(ban->who, "%s!%s@%s",
  482                           cptr->name, cptr->user->username, GET_USER_HOST(cptr));
  483     }
  484     else
  485     {
  486         ban->who = (char *) MyMalloc(strlen(cptr->name) + 1);
  487         (void) strcpy(ban->who, cptr->name);
  488     }
  489     
  490     /* determine what 'type' of mask this is, for less matching later */
  491     
  492     if(banid[0] == '*' && banid[1] == '!')
  493     {
  494         if(banid[2] == '*' && banid[3] == '@')
  495             ban->type = MTYP_HOST;
  496         else
  497             ban->type = MTYP_USERHOST;
  498     }
  499     else
  500         ban->type = MTYP_FULL;
  501 
  502     ban->when = timeofday;
  503     chptr->banlist = ban;
  504     chptr->banserial++;
  505     
  506     return 0;
  507 }
  508 
  509 /*
  510  * del_banid - delete an id belonging to cptr if banid is null,
  511  * deleteall banids belonging to cptr.
  512  */
  513 static int del_banid(aChannel *chptr, char *banid)
  514 {
  515    aBan        **ban;
  516    aBan         *tmp;
  517 
  518    if (!banid)
  519        return -1;
  520    for (ban = &(chptr->banlist); *ban; ban = &((*ban)->next))
  521        if (mycmp(banid, (*ban)->banstr) == 0)
  522        {
  523            tmp = *ban;
  524            *ban = tmp->next;
  525 
  526            chptr->banserial++;
  527 
  528            MyFree(tmp->banstr);
  529            MyFree(tmp->who);
  530            MyFree(tmp);
  531            
  532            break;
  533        }
  534    return 0;
  535 }
  536 
  537 /*
  538  * is_banned - returns CHFL_BANNED if banned else 0
  539  * 
  540  * caches banned status in chanMember for can_send()
  541  *   -Quension [Jun 2004]
  542  */
  543 
  544 static int is_banned(aClient *cptr, aChannel *chptr, chanMember *cm)
  545 {
  546     aBan       *ban;
  547 #ifdef EXEMPT_LISTS
  548     aBanExempt *exempt;
  549 #endif
  550     char        s[NICKLEN + USERLEN + HOSTLEN + 6];
  551 #ifdef USER_HOSTMASKING
  552     char        s3[NICKLEN + USERLEN + HOSTLEN + 6];
  553 #endif
  554     char       *s2;
  555     
  556     if (!IsPerson(cptr))
  557         return 0;
  558 
  559     /* if cache is valid, use it */
  560     if (cm)
  561     {
  562         if (cm->banserial == chptr->banserial)
  563             return (cm->flags & CHFL_BANNED);
  564         cm->banserial = chptr->banserial;
  565         cm->flags &= ~CHFL_BANNED;
  566     }
  567 
  568     strcpy(s, make_nick_user_host(cptr->name, cptr->user->username,
  569                                   cptr->user->host));
  570 #ifdef USER_HOSTMASKING
  571     strcpy(s3, make_nick_user_host(cptr->name, cptr->user->username,
  572                                    cptr->user->mhost));
  573 #endif
  574     s2 = make_nick_user_host(cptr->name, cptr->user->username,
  575                              cptr->hostip);
  576 
  577 #ifdef EXEMPT_LISTS
  578     for (exempt = chptr->banexempt_list; exempt; exempt = exempt->next)
  579         if (!match(exempt->banstr, s) || !match(exempt->banstr, s2) ||
  580 #ifdef USER_HOSTMASKING
  581             !match(exempt->banstr, s3) ||
  582 #endif
  583         client_matches_cidrstr(cptr, exempt->banstr))
  584             return 0;
  585 #endif
  586 
  587     for (ban = chptr->banlist; ban; ban = ban->next)
  588         if ((match(ban->banstr, s) == 0) ||
  589             (match(ban->banstr, s2) == 0) ||
  590 #ifdef USER_HOSTMASKING
  591             (match(ban->banstr, s3) == 0) ||
  592 #endif
  593         client_matches_cidrstr(cptr, ban->banstr))
  594             break;
  595 
  596     if (ban)
  597     {
  598         if (cm)
  599             cm->flags |= CHFL_BANNED;
  600         return CHFL_BANNED;
  601     }
  602 
  603     return 0;
  604 }
  605 
  606 /*
  607  * Forces the cached banned status for a user to be flushed in all the channels
  608  * they are in.
  609  */
  610 void flush_user_banserial(aClient *cptr)
  611 {
  612     Link *ptr;
  613 
  614     if (!IsPerson(cptr))
  615         return;
  616     for (ptr = cptr->user->channel; ptr; ptr = ptr->next)
  617     {
  618         aChannel *chptr = ptr->value.chptr;
  619         chanMember *cm = find_user_member(chptr->members, cptr);
  620 
  621         if (cm)
  622             cm->banserial = chptr->banserial - 1;
  623     }
  624 }
  625 
  626 aBan *nick_is_banned(aChannel *chptr, char *nick, aClient *cptr)
  627 {
  628     aBan *ban;
  629 #ifdef EXEMPT_LISTS
  630     aBanExempt *exempt;
  631 #endif
  632     char *s, s2[NICKLEN+USERLEN+HOSTLEN+6];
  633 #ifdef USER_HOSTMASKING
  634     char s3[NICKLEN+USERLEN+HOSTLEN+6];
  635 #endif
  636     
  637     if (!IsPerson(cptr)) return NULL;
  638     
  639     strcpy(s2, make_nick_user_host(nick, cptr->user->username,
  640                                    cptr->user->host));
  641 #ifdef USER_HOSTMASKING
  642     strcpy(s3, make_nick_user_host(nick, cptr->user->username,
  643                                    cptr->user->mhost));
  644 #endif
  645     s = make_nick_user_host(nick, cptr->user->username, cptr->hostip);
  646 
  647 #ifdef EXEMPT_LISTS
  648     for (exempt = chptr->banexempt_list; exempt; exempt = exempt->next)
  649         if (exempt->type == MTYP_FULL &&
  650             ((match(exempt->banstr, s2) == 0) ||
  651 #ifdef USER_HOSTMASKING
  652              (match(exempt->banstr, s3) == 0) ||
  653 #endif
  654              (match(exempt->banstr, s) == 0) ||
  655          client_matches_cidrstr(cptr, exempt->banstr)))
  656             return NULL;
  657 #endif
  658 
  659     for (ban = chptr->banlist; ban; ban = ban->next)
  660         if (ban->type == MTYP_FULL &&        /* only check applicable bans */
  661             ((match(ban->banstr, s2) == 0) ||    /* check host before IP */
  662 #ifdef USER_HOSTMASKING
  663              (match(ban->banstr, s3) == 0) ||
  664 #endif
  665              (match(ban->banstr, s) == 0) ||
  666          client_matches_cidrstr(cptr, ban->banstr)))
  667             break;
  668     return (ban);
  669 }
  670 
  671 void remove_matching_bans(aChannel *chptr, aClient *cptr, aClient *from) 
  672 {
  673     aBan *ban, *bnext;
  674     char targhost[NICKLEN+USERLEN+HOSTLEN+6];
  675 #ifdef USER_HOSTMASKING
  676     char targmhost[NICKLEN+USERLEN+HOSTLEN+6];
  677 #endif
  678     char targip[NICKLEN+USERLEN+HOSTLEN+6];
  679     char *m;
  680     int count = 0, send = 0;
  681     
  682     if (!IsPerson(cptr)) return;
  683     
  684     strcpy(targhost, make_nick_user_host(cptr->name, cptr->user->username,
  685                                          cptr->user->host));
  686 #ifdef USER_HOSTMASKING
  687     strcpy(targmhost, make_nick_user_host(cptr->name, cptr->user->username,
  688                                           cptr->user->mhost));
  689 #endif
  690   strcpy(targip, make_nick_user_host(cptr->name, cptr->user->username,
  691                                      cptr->hostip));
  692   
  693   m = modebuf;  
  694   *m++ = '-';
  695   *m = '\0'; 
  696   
  697   *parabuf = '\0';
  698   
  699   ban = chptr->banlist;
  700   
  701   while(ban)
  702   {
  703       bnext = ban->next;
  704       if((match(ban->banstr, targhost) == 0) ||
  705 #ifdef USER_HOSTMASKING
  706          (match(ban->banstr, targmhost) == 0) ||
  707 #endif
  708          (match(ban->banstr, targip) == 0) ||
  709      client_matches_cidrstr(cptr, ban->banstr))
  710       {
  711           if (strlen(parabuf) + strlen(ban->banstr) + 10 < (size_t) MODEBUFLEN)
  712           {
  713               if(*parabuf)
  714                   strcat(parabuf, " ");
  715               strcat(parabuf, ban->banstr);
  716               count++;
  717               *m++ = 'b';
  718               *m = '\0';
  719           }
  720           else 
  721               if(*parabuf)
  722                   send = 1;
  723           
  724           if(count == MAXTSMODEPARAMS)
  725               send = 1;
  726           
  727           if(send)
  728           {
  729               sendto_channel_butserv_me(chptr, from, ":%s MODE %s %s %s", 
  730                                         from->name, chptr->chname, modebuf,
  731                                         parabuf);
  732               sendto_serv_butone(from, ":%s MODE %s %ld %s %s", from->name,
  733                                  chptr->chname, chptr->channelts, modebuf,
  734                                  parabuf);
  735               send = 0;
  736               *parabuf = '\0';
  737               m = modebuf;
  738               *m++ = '-';
  739               if(count != MAXTSMODEPARAMS)
  740               {
  741                   strcpy(parabuf, ban->banstr);
  742                   *m++ = 'b';
  743                   count = 1;
  744               }
  745               else
  746                   count = 0;
  747               *m = '\0';
  748           }
  749           
  750           del_banid(chptr, ban->banstr);
  751       }
  752       ban = bnext;
  753   }
  754   
  755   if(*parabuf)
  756   {
  757       sendto_channel_butserv_me(chptr, from, ":%s MODE %s %s %s", from->name,
  758                                 chptr->chname, modebuf, parabuf);
  759       sendto_serv_butone(from, ":%s MODE %s %ld %s %s", from->name,
  760                          chptr->chname, chptr->channelts, modebuf, parabuf);
  761   }
  762   
  763   return;
  764 }
  765 
  766 #ifdef EXEMPT_LISTS
  767 void remove_matching_exempts(aChannel *chptr, aClient *cptr, aClient *from)
  768 {
  769     aBanExempt *ex, *enext;
  770     char targhost[NICKLEN+USERLEN+HOSTLEN+6];
  771 #ifdef USER_HOSTMASKING
  772     char targmhost[NICKLEN+USERLEN+HOSTLEN+6];
  773 #endif
  774     char targip[NICKLEN+USERLEN+HOSTLEN+6];
  775     char *m;
  776     int count = 0, send = 0;
  777 
  778     if (!IsPerson(cptr)) return;
  779 
  780     strcpy(targhost, make_nick_user_host(cptr->name, cptr->user->username,
  781                                          cptr->user->host));
  782 #ifdef USER_HOSTMASKING
  783     strcpy(targmhost, make_nick_user_host(cptr->name, cptr->user->username,
  784                                           cptr->user->mhost));
  785 #endif
  786     strcpy(targip, make_nick_user_host(cptr->name, cptr->user->username,
  787                                        cptr->hostip));
  788 
  789     m = modebuf;
  790     *m++ = '-';
  791     *m = '\0';
  792 
  793     *parabuf = '\0';
  794 
  795     ex = chptr->banexempt_list;
  796 
  797     while(ex)
  798     {
  799         enext = ex->next;
  800         if((match(ex->banstr, targhost) == 0) ||
  801 #ifdef USER_HOSTMASKING
  802            (match(ex->banstr, targmhost) == 0) ||
  803 #endif
  804            (match(ex->banstr, targip) == 0) ||
  805        client_matches_cidrstr(cptr, ex->banstr))
  806         {
  807             if (strlen(parabuf) + strlen(ex->banstr) + 10 < (size_t) MODEBUFLEN)
  808             {
  809                 if(*parabuf)
  810                     strcat(parabuf, " ");
  811                 strcat(parabuf, ex->banstr);
  812                 count++;
  813                 *m++ = 'e';
  814                 *m = '\0';
  815             }
  816             else
  817                 if(*parabuf)
  818                     send = 1;
  819 
  820             if(count == MAXTSMODEPARAMS)
  821                 send = 1;
  822 
  823             if(send)
  824             {
  825                 sendto_channel_butserv_me(chptr, from, ":%s MODE %s %s %s",
  826                                           from->name, chptr->chname, modebuf,
  827                                           parabuf);
  828                 sendto_serv_butone(from, ":%s MODE %s %ld %s %s", from->name,
  829                                    chptr->chname, chptr->channelts, modebuf,
  830                                    parabuf);
  831                 send = 0;
  832                 *parabuf = '\0';
  833                 m = modebuf;
  834                 *m++ = '-';
  835                 if(count != MAXTSMODEPARAMS)
  836                 {
  837                     strcpy(parabuf, ex->banstr);
  838                     *m++ = 'e';
  839                     count = 1;
  840                 }
  841                 else
  842                     count = 0;
  843                 *m = '\0';
  844             }
  845 
  846             del_exempt_id(chptr, ex->banstr);
  847         }
  848         ex = enext;
  849     }
  850 
  851     if(*parabuf)
  852     {
  853         sendto_channel_butserv_me(chptr, from, ":%s MODE %s %s %s", from->name,
  854                                   chptr->chname, modebuf, parabuf);
  855         sendto_serv_butone(from, ":%s MODE %s %ld %s %s", from->name,
  856                            chptr->chname, chptr->channelts, modebuf, parabuf);
  857     }
  858 
  859     return;
  860 }
  861 #endif
  862 
  863 #ifdef INVITE_LISTS
  864 void remove_matching_invites(aChannel *chptr, aClient *cptr, aClient *from)
  865 {
  866     anInvite *inv, *inext;
  867     char targhost[NICKLEN+USERLEN+HOSTLEN+6];
  868 #ifdef USER_HOSTMASKING
  869     char targmhost[NICKLEN+USERLEN+HOSTLEN+6];
  870 #endif
  871     char targip[NICKLEN+USERLEN+HOSTLEN+6];
  872     char *m;
  873     int count = 0, send = 0;
  874 
  875     if (!IsPerson(cptr)) return;
  876 
  877     strcpy(targhost, make_nick_user_host(cptr->name, cptr->user->username,
  878                                          cptr->user->host));
  879 #ifdef USER_HOSTMASKING
  880     strcpy(targmhost, make_nick_user_host(cptr->name, cptr->user->username,
  881                                           cptr->user->mhost));
  882 #endif
  883     strcpy(targip, make_nick_user_host(cptr->name, cptr->user->username,
  884                                        cptr->hostip));
  885 
  886     m = modebuf;
  887     *m++ = '-';
  888     *m = '\0';
  889 
  890     *parabuf = '\0';
  891 
  892     inv = chptr->invite_list;
  893 
  894     while(inv)
  895     {
  896         inext = inv->next;
  897         if((match(inv->invstr, targhost) == 0) ||
  898 #ifdef USER_HOSTMASKING
  899            (match(inv->invstr, targmhost) == 0) ||
  900 #endif
  901            (match(inv->invstr, targip) == 0))
  902         {
  903             if (strlen(parabuf) + strlen(inv->invstr) + 10 < (size_t) MODEBUFLEN)
  904             {
  905                 if(*parabuf)
  906                     strcat(parabuf, " ");
  907                 strcat(parabuf, inv->invstr);
  908                 count++;
  909                 *m++ = 'I';
  910                 *m = '\0';
  911             }
  912             else
  913                 if(*parabuf)
  914                     send = 1;
  915 
  916             if(count == MAXTSMODEPARAMS)
  917                 send = 1;
  918 
  919             if(send)
  920             {
  921                 sendto_channel_butserv_me(chptr, from, ":%s MODE %s %s %s",
  922                                           from->name, chptr->chname, modebuf,
  923                                           parabuf);
  924                 sendto_serv_butone(from, ":%s MODE %s %ld %s %s", from->name,
  925                                    chptr->chname, chptr->channelts, modebuf,
  926                                    parabuf);
  927                 send = 0;
  928                 *parabuf = '\0';
  929                 m = modebuf;
  930                 *m++ = '-';
  931                 if(count != MAXTSMODEPARAMS)
  932                 {
  933                     strcpy(parabuf, inv->invstr);
  934                     *m++ = 'I';
  935                     count = 1;
  936                 }
  937                 else
  938                     count = 0;
  939                 *m = '\0';
  940             }
  941 
  942             del_invite_id(chptr, inv->invstr);
  943         }
  944         inv = inext;
  945     }
  946 
  947     if(*parabuf)
  948     {
  949         sendto_channel_butserv_me(chptr, from, ":%s MODE %s %s %s", from->name,
  950                                   chptr->chname, modebuf, parabuf);
  951         sendto_serv_butone(from, ":%s MODE %s %ld %s %s", from->name,
  952                            chptr->chname, chptr->channelts, modebuf, parabuf);
  953     }
  954 
  955     return;
  956 }
  957 #endif
  958 
  959 
  960 /* refill join rate warning token bucket, and count a join attempt */
  961 static void
  962 jrw_update(aChannel *chptr, int local)
  963 {
  964     int adj_delta;
  965     int bkt_delta;
  966 
  967     if (chptr->jrw_bucket < DEFAULT_JOIN_SIZE && NOW > chptr->jrw_last)
  968     {
  969         adj_delta = NOW - chptr->jrw_last;
  970         bkt_delta = DEFAULT_JOIN_SIZE - chptr->jrw_bucket;
  971         
  972         /* avoid overflow for long timespans */
  973         if (adj_delta < bkt_delta)
  974             adj_delta *= DEFAULT_JOIN_NUM;
  975         
  976         if (adj_delta > bkt_delta)
  977             adj_delta = bkt_delta;
  978         
  979         chptr->jrw_bucket += adj_delta;
  980         
  981         /* bucket has a free fill (not join) slot, reset debt counter */
  982         if (chptr->jrw_bucket >= DEFAULT_JOIN_NUM)
  983         {
  984             chptr->jrw_debt_ctr = 0;
  985             chptr->jrw_debt_ts = 0;
  986         }
  987     }
  988     
  989     if (chptr->jrw_bucket >= -(DEFAULT_JOIN_SIZE - DEFAULT_JOIN_TIME))
  990         chptr->jrw_bucket -= DEFAULT_JOIN_TIME;
  991     
  992     /* warning bucket is always current, which pins it at the rate limit */
  993     chptr->jrw_last = NOW;
  994     
  995     /* for statistical purposes, keep count of local join attempts */
  996     if (local)
  997         chptr->jrw_debt_ctr++;
  998 
  999     /* statistical timestamp reflects all joins */
 1000     if (chptr->jrw_debt_ts == 0)
 1001         chptr->jrw_debt_ts = NOW;
 1002 }
 1003 
 1004 /* refill join rate throttling token bucket */
 1005 static void
 1006 jrl_update(aChannel *chptr)
 1007 {
 1008     int adj_delta;
 1009     int bkt_delta;
 1010     int jnum, jsize;
 1011 
 1012     jnum = chptr->mode.jr_num;
 1013     jsize = chptr->mode.jrl_size;
 1014     
 1015     /* throttling disabled */
 1016     if (!jsize)
 1017         return;
 1018     
 1019     if (chptr->jrl_bucket < jsize && NOW > chptr->jrl_last)
 1020     {
 1021         adj_delta = NOW - chptr->jrl_last;
 1022         bkt_delta = jsize - chptr->jrl_bucket;
 1023 
 1024         /* avoid overflow for long timespans */
 1025         if (adj_delta < bkt_delta)
 1026             adj_delta *= jnum;
 1027 
 1028         if (adj_delta > bkt_delta)
 1029             adj_delta = bkt_delta;
 1030 
 1031         chptr->jrl_bucket += adj_delta;
 1032         chptr->jrl_last = NOW;
 1033     }
 1034 }
 1035 
 1036 /*
 1037  * Do pre-JOIN updates.  Called for local joins only.
 1038  */
 1039 static void
 1040 joinrate_prejoin(aChannel *chptr)
 1041 {
 1042     jrl_update(chptr);
 1043     jrw_update(chptr, 1);
 1044 }
 1045 
 1046 /*
 1047  * Check if a join would be allowed, warning if appropriate.
 1048  * Called for local joins only.
 1049  */
 1050 static int
 1051 joinrate_check(aChannel *chptr, aClient *cptr, int warn)
 1052 {
 1053     int jnum, jtime, jsize;
 1054     
 1055     jnum = chptr->mode.jr_num;
 1056     jtime = chptr->mode.jr_time;
 1057     jsize = chptr->mode.jrl_size;
 1058     
 1059     /* join throttling disabled */
 1060     if (!jsize)
 1061         return 1;
 1062     
 1063     /* free slot in bucket */
 1064     if (chptr->jrl_bucket >= jtime)
 1065         return 1;
 1066     
 1067     /* throttled */
 1068     if (warn)
 1069     {
 1070         if (call_hooks(CHOOK_THROTTLE, cptr, chptr, 1, jnum, jtime) != FLUSH_BUFFER)
 1071             sendto_realops_lev(DEBUG_LEV, "Join rate throttling on %s for"
 1072                                " %s!%s@%s (%d%s in %d)", chptr->chname,
 1073                                cptr->name, cptr->user->username, cptr->user->host,
 1074                                jnum, (chptr->jrl_bucket < 0) ? "+" : "", jtime);
 1075     }
 1076     return 0;
 1077 }
 1078 
 1079 /*
 1080  * Do post-JOIN updates.  Called for both local and remote joins.
 1081  */
 1082 static void
 1083 joinrate_dojoin(aChannel *chptr, aClient *cptr)
 1084 {
 1085     int jtime, jsize;
 1086     int local;
 1087     
 1088     local = MyConnect(cptr);
 1089     jtime = chptr->mode.jr_time;
 1090     jsize = chptr->mode.jrl_size;
 1091     
 1092     if (!local)
 1093     {
 1094         jrw_update(chptr, 0);
 1095         jrl_update(chptr);
 1096     }
 1097     else if (chptr->jrw_bucket <= 0 && chptr->jrw_debt_ctr)
 1098     {
 1099         if (call_hooks(CHOOK_THROTTLE, cptr, chptr, 2, chptr->jrw_debt_ctr, NOW - chptr->jrw_debt_ts) != FLUSH_BUFFER)
 1100             sendto_realops_lev(DEBUG_LEV, "Join rate warning on %s for %s!%s@%s"
 1101                                " (%d in %ld) [joined]", chptr->chname,
 1102                                cptr->name, cptr->user->username, cptr->user->host,
 1103                                chptr->jrw_debt_ctr, (long)(NOW - chptr->jrw_debt_ts));
 1104     }
 1105 
 1106     /* remote joins cause negative penalty here (distributed throttling) */
 1107     /* WARNING: joinrate_check must have allowed a local join */
 1108     if (jsize)
 1109     {
 1110         if (local || chptr->jrl_bucket >= -(jsize - jtime))
 1111         {
 1112             chptr->jrl_bucket -= jtime;
 1113             chptr->jrl_last = NOW;
 1114         }
 1115     }
 1116 }
 1117 
 1118 /*
 1119  * Send a warning notice if appropriate.  Called for local failed joins.
 1120  */
 1121 static void
 1122 joinrate_warn(aChannel *chptr, aClient *cptr)
 1123 {
 1124     /* no slots free */
 1125     if (chptr->jrw_bucket <= 0 && chptr->jrw_debt_ctr)
 1126     {
 1127         if (call_hooks(CHOOK_THROTTLE, cptr, chptr, 3, chptr->jrw_debt_ctr, NOW - chptr->jrw_debt_ts) != FLUSH_BUFFER)
 1128             sendto_realops_lev(DEBUG_LEV, "Join rate warning on %s for %s!%s@%s"
 1129                                " (%d in %ld) [failed]", chptr->chname,
 1130                                cptr->name, cptr->user->username,
 1131                                cptr->user->host,
 1132                                chptr->jrw_debt_ctr, (long)(NOW - chptr->jrw_debt_ts));
 1133     }
 1134 }
 1135 
 1136 
 1137 /*
 1138  * adds a user to a channel by adding another link to the channels
 1139  * member chain.
 1140  */
 1141 void add_user_to_channel(aChannel *chptr, aClient *who, int flags)
 1142 {
 1143     Link   *ptr;
 1144     chanMember *cm;
 1145     
 1146 #ifdef DUMP_DEBUG
 1147     fprintf(dumpfp,"Add to channel %s: %p:%s\n",chptr->chname,who,who->name);
 1148 #endif
 1149     
 1150     if (who->user)
 1151     {
 1152         cm = make_chanmember();
 1153         cm->flags = flags;
 1154         cm->cptr = who;
 1155         cm->next = chptr->members;
 1156         cm->banserial = chptr->banserial;
 1157         cm->when = NOW;
 1158         cm->last_message_number = 0;
 1159         cm->last_message_time = 0;
 1160 
 1161         chptr->members = cm;
 1162         chptr->users++;
 1163         
 1164         ptr = make_link();
 1165         ptr->value.chptr = chptr;
 1166         ptr->next = who->user->channel;
 1167         who->user->channel = ptr;
 1168         who->user->joined++;
 1169     }
 1170 }
 1171 
 1172 void remove_user_from_channel(aClient *sptr, aChannel *chptr)
 1173 {
 1174     chanMember  **curr, *tmp;
 1175     Link           **lcurr, *ltmp;
 1176     
 1177     for (curr = &chptr->members; (tmp = *curr); curr = &tmp->next)
 1178         if (tmp->cptr == sptr)
 1179         {
 1180             *curr = tmp->next;
 1181             free_chanmember(tmp);
 1182             break;
 1183         }
 1184 
 1185     for (lcurr = &sptr->user->channel; (ltmp = *lcurr); lcurr = &ltmp->next)
 1186         if (ltmp->value.chptr == chptr)
 1187         {
 1188             *lcurr = ltmp->next;
 1189             free_link(ltmp);
 1190             break;
 1191         }
 1192     sptr->user->joined--;
 1193     sub1_from_channel(chptr);
 1194 }
 1195 
 1196 int is_chan_op(aClient *cptr, aChannel *chptr)
 1197 {
 1198     chanMember   *cm;
 1199     
 1200     if (chptr)
 1201         if ((cm = find_user_member(chptr->members, cptr)))
 1202             return (cm->flags & CHFL_CHANOP);
 1203     
 1204     return 0;
 1205 }
 1206 
 1207 int is_chan_halfop(aClient *cptr, aChannel *chptr)
 1208 {
 1209     chanMember   *cm;
 1210     
 1211     if (chptr)
 1212         if ((cm = find_user_member(chptr->members, cptr)))
 1213             return (cm->flags & CHFL_HALFOP);
 1214     
 1215     return 0;
 1216 }
 1217 
 1218 /* A function to check if a user can use the kick command
 1219    Returns:
 1220    2 - user is an op (@)
 1221    1 - user is an half-op (%)
 1222    0 - user is not an op or half-op
 1223  */
 1224 inline int is_chan_cankick(aClient *cptr, aChannel *chptr)
 1225 {
 1226     chanMember   *cm;
 1227     
 1228     if (chptr)
 1229         if ((cm = find_user_member(chptr->members, cptr)))
 1230         {
 1231             if(cm->flags & CHFL_CHANOP)
 1232                 return 2;
 1233             else if(cm->flags & CHFL_HALFOP)
 1234                 return 1;
 1235             else return 0;
 1236         }
 1237     
 1238     return 0;
 1239 }
 1240 
 1241 int is_chan_opvoice(aClient *cptr, aChannel *chptr)
 1242 {
 1243     chanMember   *cm;
 1244     
 1245     if (chptr)
 1246         if ((cm = find_user_member(chptr->members, cptr)))
 1247             return ((cm->flags & CHFL_CHANOP) || (cm->flags & CHFL_HALFOP) || (cm->flags & CHFL_VOICE));
 1248     
 1249     return 0;
 1250 }
 1251 
 1252 int is_deopped(aClient *cptr, aChannel *chptr)
 1253 {
 1254     chanMember   *cm;
 1255     
 1256     if (chptr)
 1257         if ((cm = find_user_member(chptr->members, cptr)))
 1258             return (cm->flags & CHFL_DEOPPED);
 1259     
 1260     return 0;
 1261 }
 1262 
 1263 int has_voice(aClient *cptr, aChannel *chptr)
 1264 {
 1265     chanMember   *cm;
 1266     
 1267     if (chptr)
 1268         if ((cm = find_user_member(chptr->members, cptr)))
 1269             return (cm->flags & CHFL_VOICE);
 1270     
 1271     return 0;
 1272 }
 1273 
 1274 time_t get_user_jointime(aClient *cptr, aChannel *chptr)
 1275 {
 1276     chanMember   *cm;
 1277 
 1278     if (chptr)
 1279         if ((cm = find_user_member(chptr->members, cptr)))
 1280             return cm->when;
 1281 
 1282     return 0;
 1283 }
 1284 
 1285 time_t get_user_lastmsgtime(aClient *cptr, aChannel *chptr)
 1286 {
 1287     chanMember   *cm;
 1288 
 1289     if (chptr)
 1290         if ((cm = find_user_member(chptr->members, cptr)))
 1291             return cm->last_message_time;
 1292 
 1293     return 0;
 1294 }
 1295 
 1296 /* is_xflags_exempted - Check if a user is exempted from the channel's xflags */
 1297 int is_xflags_exempted(aClient *sptr, aChannel *chptr)
 1298 {
 1299     if(IsAnOper(sptr)) return 1; /* IRC Operators are always exempted */
 1300     if((chptr->xflags & XFLAG_EXEMPT_OPPED) && (chptr->xflags & XFLAG_EXEMPT_VOICED))
 1301     {
 1302       if(is_chan_opvoice(sptr,chptr)) return 1;
 1303     }
 1304     else
 1305     {
 1306       if((chptr->xflags & XFLAG_EXEMPT_OPPED) && is_chan_op(sptr,chptr)) return 1;
 1307       if((chptr->xflags & XFLAG_EXEMPT_VOICED) && has_voice(sptr,chptr)) return 1;
 1308     }
 1309     if((chptr->xflags & XFLAG_EXEMPT_REGISTERED) && IsRegNick(sptr)) return 1;
 1310     if((chptr->xflags & XFLAG_EXEMPT_IDENTD) && sptr->user && sptr->user->username[0]!='~') return 1;
 1311     if((chptr->xflags & XFLAG_EXEMPT_WEBIRC) && MyClient(sptr) && sptr->webirc_ip) return 1;
 1312     return 0;
 1313 }
 1314 
 1315 /* A function to send a (verbose) message to the relay channel if it exists
 1316    (and isn't moderated)... */
 1317 int verbose_to_relaychan(aClient *sptr, aChannel *chptr, char *cmd, char *reason)
 1318 {
 1319     aChannel *relaychan_ptr;
 1320     char relaychan_name[CHANNELLEN + 1];
 1321 
 1322     if(strlen(chptr->chname)+6 > CHANNELLEN)
 1323         return 0; /* Channel is too long.. we must be able to add -relay to it... */
 1324 
 1325     strcpy(relaychan_name, chptr->chname);
 1326     strcat(relaychan_name, "-relay");
 1327 
 1328     if(!(relaychan_ptr = find_channel(relaychan_name, NULL)))
 1329         return 0; /* Relay channel doesn't exist */
 1330 
 1331     if(relaychan_ptr->mode.mode & MODE_MODERATED)
 1332         return 0; /* Relay channel is moderated */
 1333 
 1334     if(reason)
 1335         sendto_channel_butone(NULL, &me, relaychan_ptr, ":%s PRIVMSG %s :Failed %s by %s!%s@%s - %s",
 1336                               me.name, relaychan_ptr->chname, cmd, sptr->name, sptr->user->username,
 1337 #ifdef USER_HOSTMASKING
 1338                               IsUmodeH(sptr)?sptr->user->mhost:
 1339 #endif
 1340                               sptr->user->host, reason);
 1341     else
 1342         sendto_channel_butone(NULL, &me, relaychan_ptr, ":%s PRIVMSG %s :Failed %s by %s!%s@%s",
 1343                               me.name, relaychan_ptr->chname, cmd, sptr->name, sptr->user->username,
 1344 #ifdef USER_HOSTMASKING
 1345                               IsUmodeH(sptr)?sptr->user->mhost:
 1346 #endif
 1347                               sptr->user->host);
 1348 
 1349     return 0;
 1350 }
 1351 
 1352 /* A function to send a (verbose) message to +f opers */
 1353 inline void verbose_to_opers(aClient *sptr, aChannel *chptr, char *cmd, char *reason)
 1354 {
 1355     if(call_hooks(CHOOK_FLOODWARN, sptr, chptr, 1, cmd, reason) == FLUSH_BUFFER) return;
 1356 
 1357     if(reason)
 1358         sendto_realops_lev(FLOOD_LEV, "Flood -- Failed %s by %s!%s@%s - %s",
 1359                            cmd, sptr->name, sptr->user->username,
 1360                            sptr->user->host, reason);
 1361     else
 1362         sendto_realops_lev(FLOOD_LEV, "Flood -- Failed %s by %s!%s@%s",
 1363                            cmd, sptr->name, sptr->user->username,
 1364                            sptr->user->host);
 1365 }
 1366 
 1367 int can_send(aClient *cptr, aChannel *chptr, char *msg)
 1368 {
 1369     chanMember   *cm;
 1370     int           ismine;
 1371     
 1372     if (IsServer(cptr) || IsULine(cptr))
 1373         return 0;
 1374     
 1375     cm = find_user_member(chptr->members, cptr);
 1376     ismine = MyClient(cptr);
 1377     
 1378     if(!cm)
 1379     {
 1380         if (chptr->mode.mode & MODE_MODERATED)
 1381             return (MODE_MODERATED);
 1382         if(chptr->mode.mode & MODE_NOPRIVMSGS)
 1383             return (MODE_NOPRIVMSGS);
 1384         if ((chptr->mode.mode & MODE_MODREG) && !IsRegNick(cptr))
 1385             return (ERR_NEEDREGGEDNICK);
 1386         if (ismine)
 1387         {
 1388             if ((chptr->mode.mode & MODE_NOCTRL) && msg_has_ctrls(msg))
 1389                 return (ERR_NOCTRLSONCHAN);
 1390             if (is_banned(cptr, chptr, NULL))
 1391                 return (MODE_BAN); /*
 1392                                 * channel is -n and user is not there;
 1393                                 * we need to bquiet them if we can
 1394                                 */
 1395         }
 1396     }
 1397     else
 1398     {
 1399         /* ops and voices can talk through everything except NOCTRL */
 1400         if (!(cm->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE)))
 1401         {
 1402             if (chptr->mode.mode & MODE_MODERATED)
 1403                 return (MODE_MODERATED);
 1404             if (is_banned(cptr, chptr, cm))
 1405                 return (MODE_BAN);
 1406             if ((chptr->mode.mode & MODE_MODREG) && !IsRegNick(cptr))
 1407                 return (ERR_NEEDREGGEDNICK);
 1408         }
 1409         if ((chptr->mode.mode & MODE_NOCTRL) && msg_has_ctrls(msg))
 1410             return (ERR_NOCTRLSONCHAN);
 1411         if(ismine)
 1412         {
 1413             if (chptr->talk_connect_time && (cptr->firsttime + chptr->talk_connect_time > NOW) && !is_xflags_exempted(cptr,chptr))
 1414                 return (ERR_NEEDTOWAIT);
 1415             if (chptr->talk_join_time && (cm->when + chptr->talk_join_time > NOW) && !is_xflags_exempted(cptr,chptr))
 1416                 return (ERR_NEEDTOWAIT);
 1417             if (chptr->max_messages && chptr->max_messages_time && !is_xflags_exempted(cptr,chptr))
 1418             {
 1419                 if ((NOW - cm->last_message_time) < chptr->max_messages_time)
 1420                 {
 1421                     if (cm->last_message_number > chptr->max_messages)
 1422                         return (ERR_MAXMSGSENT);
 1423                     else
 1424                         cm->last_message_number++;
 1425                 }
 1426                 else
 1427                     cm->last_message_number = 1;
 1428 
 1429                 cm->last_message_time = NOW;
 1430             }
 1431         }
 1432     }
 1433     
 1434     return 0;
 1435 }
 1436 
 1437 /*
 1438  * write the "simple" list of channel modes for channel chptr onto
 1439  * buffer mbuf with the parameters in pbuf.
 1440  */
 1441 static void channel_modes(aClient *cptr, char *mbuf, char *pbuf,
 1442                           aChannel *chptr)
 1443 {
 1444     pbuf[0] = '\0';
 1445     *mbuf++ = '+';
 1446     if (chptr->mode.mode & MODE_SECRET)
 1447         *mbuf++ = 's';
 1448     if (chptr->mode.mode & MODE_PRIVATE)
 1449         *mbuf++ = 'p';
 1450     if (chptr->mode.mode & MODE_MODERATED)
 1451         *mbuf++ = 'm';
 1452     if (chptr->mode.mode & MODE_TOPICLIMIT)
 1453         *mbuf++ = 't';
 1454     if (chptr->mode.mode & MODE_INVITEONLY)
 1455         *mbuf++ = 'i';
 1456     if (chptr->mode.mode & MODE_NOPRIVMSGS)
 1457         *mbuf++ = 'n';
 1458     if (chptr->mode.mode & MODE_REGISTERED)
 1459         *mbuf++ = 'r';
 1460     if (chptr->mode.mode & MODE_REGONLY)
 1461         *mbuf++ = 'R';
 1462     if (chptr->mode.mode & MODE_NOCTRL)
 1463         *mbuf++ = 'c';
 1464     if (chptr->mode.mode & MODE_OPERONLY)
 1465         *mbuf++ = 'O';
 1466     if (chptr->mode.mode & MODE_MODREG)
 1467         *mbuf++ = 'M';
 1468     if (chptr->mode.mode & MODE_SSLONLY)
 1469         *mbuf++ = 'S';
 1470     if (chptr->mode.mode & MODE_AUDITORIUM)
 1471         *mbuf++ = 'A';
 1472     if (chptr->mode.mode & MODE_PRIVACY)
 1473         *mbuf++ = 'P';
 1474 #ifdef USE_CHANMODE_L
 1475     if (chptr->mode.mode & MODE_LISTED)
 1476         *mbuf++ = 'L';
 1477 #endif
 1478     if (chptr->mode.limit) 
 1479     {
 1480         *mbuf++ = 'l';
 1481         if (IsMember(cptr, chptr) || IsServer(cptr) || IsULine(cptr) || IsAnOper(cptr))
 1482             ircsprintf(pbuf, "%d", chptr->mode.limit);
 1483     }
 1484     if (chptr->mode.mode & MODE_JOINRATE)
 1485     {
 1486         *mbuf++ = 'j';
 1487 
 1488         if (IsMember(cptr, chptr) || IsServer(cptr) || IsULine(cptr) || IsAnOper(cptr))
 1489         {
 1490             char tmp[16];
 1491             if(pbuf[0] != '\0')
 1492                 strcat(pbuf, " ");
 1493 
 1494             if(chptr->mode.jr_num == 0 || chptr->mode.jr_time == 0)
 1495                 ircsprintf(tmp, "0");
 1496             else
 1497                 ircsprintf(tmp, "%d:%d", chptr->mode.jr_num, 
 1498                             chptr->mode.jr_time);
 1499 
 1500             strcat(pbuf, tmp);
 1501         }
 1502     }
 1503     if (*chptr->mode.key)
 1504     {
 1505         *mbuf++ = 'k';
 1506         if (IsMember(cptr, chptr) || IsServer(cptr) || IsULine(cptr))
 1507         {
 1508             if(pbuf[0] != '\0')
 1509                 strcat(pbuf, " ");
 1510             strcat(pbuf, chptr->mode.key);
 1511         } else if (IsOper(cptr)) {
 1512             if(pbuf[0] != '\0')
 1513                 strcat(pbuf, " ");
 1514             strcat(pbuf, "*");
 1515         }
 1516     }
 1517     *mbuf++ = '\0';
 1518     return;
 1519 }
 1520 
 1521 static void send_channel_lists(aClient *cptr, aChannel *chptr)
 1522 {
 1523     aBan   *bp;
 1524 #ifdef EXEMPT_LISTS
 1525     aBanExempt *exempt;
 1526 #endif
 1527 #ifdef INVITE_LISTS
 1528     anInvite *inv;
 1529 #endif            
 1530     char   *cp;
 1531     int         count = 0, send = 0;
 1532 
 1533     cp = modebuf + strlen(modebuf);
 1534 
 1535     if (*parabuf) /* mode +l or +k xx */
 1536         count = 1;
 1537 
 1538     for (bp = chptr->banlist; bp; bp = bp->next) 
 1539     {
 1540         if (strlen(parabuf) + strlen(bp->banstr) + 20 < (size_t) MODEBUFLEN) 
 1541         {
 1542             if(*parabuf)
 1543                 strcat(parabuf, " ");
 1544             strcat(parabuf, bp->banstr);
 1545             count++;
 1546             *cp++ = 'b';
 1547             *cp = '\0';
 1548         }
 1549         else if (*parabuf)
 1550             send = 1;
 1551 
 1552         if (count == MAXTSMODEPARAMS)
 1553             send = 1;
 1554 
 1555         if (send) 
 1556         {
 1557             sendto_one(cptr, ":%s MODE %s %ld %s %s", me.name, chptr->chname,
 1558                            chptr->channelts, modebuf, parabuf);
 1559             send = 0;
 1560             *parabuf = '\0';
 1561             cp = modebuf;
 1562             *cp++ = '+';
 1563             if (count != MAXTSMODEPARAMS) 
 1564             {
 1565                 strcpy(parabuf, bp->banstr);
 1566                 *cp++ = 'b';
 1567                 count = 1;
 1568             }
 1569             else
 1570                 count = 0;
 1571             *cp = '\0';
 1572         }
 1573     }
 1574 #ifdef EXEMPT_LISTS
 1575     for (exempt = chptr->banexempt_list; exempt; exempt = exempt->next)
 1576     {
 1577         if (strlen(parabuf) + strlen(exempt->banstr) + 20 < (size_t)MODEBUFLEN)
 1578         {
 1579             if (*parabuf) strcat(parabuf, " ");
 1580             strcat(parabuf, exempt->banstr);
 1581             count++;
 1582             *cp++ = 'e';
 1583             *cp = 0;
 1584         }
 1585         else if (*parabuf)
 1586             send = 1;
 1587         
 1588         
 1589         if (count == MAXTSMODEPARAMS)
 1590             send = 1;
 1591         
 1592         if (send)
 1593         {
 1594             sendto_one(cptr, ":%s MODE %s %ld %s %s", me.name, chptr->chname,
 1595                            chptr->channelts, modebuf, parabuf);
 1596             send = 0;
 1597             *parabuf = 0;
 1598             cp = modebuf;
 1599             *cp++ = '+';
 1600             if (count != MAXTSMODEPARAMS)
 1601             {
 1602                 strcpy(parabuf, exempt->banstr);
 1603                 *cp++ = 'e';
 1604                 count = 1;
 1605             }
 1606             else count = 0;
 1607             *cp = 0;
 1608         }
 1609     }
 1610 #endif    
 1611 #ifdef INVITE_LISTS
 1612     for (inv = chptr->invite_list; inv; inv = inv->next)
 1613     {
 1614         if (strlen(parabuf) + strlen(inv->invstr) + 20 < (size_t)MODEBUFLEN)
 1615         {
 1616             if (*parabuf) strcat(parabuf, " ");
 1617             strcat(parabuf, inv->invstr);
 1618             count++;
 1619             *cp++ = 'I';
 1620             *cp = 0;
 1621         }
 1622         else if (*parabuf)
 1623             send = 1;
 1624         
 1625         
 1626         if (count == MAXTSMODEPARAMS)
 1627             send = 1;
 1628         
 1629         if (send)
 1630         {
 1631             sendto_one(cptr, ":%s MODE %s %ld %s %s", me.name, chptr->chname,
 1632                            chptr->channelts, modebuf, parabuf);
 1633             send = 0;
 1634             *parabuf = 0;
 1635             cp = modebuf;
 1636             *cp++ = '+';
 1637             if (count != MAXTSMODEPARAMS)
 1638             {
 1639                 strcpy(parabuf, inv->invstr);
 1640                 *cp++ = 'I';
 1641                 count = 1;
 1642             }
 1643             else count = 0;
 1644             *cp = 0;
 1645         }
 1646     }
 1647 #endif    
 1648     
 1649 }
 1650 
 1651 /* send "cptr" a full list of the modes for channel chptr. */
 1652 void send_channel_modes(aClient *cptr, aChannel *chptr)
 1653 {
 1654     chanMember       *l, *anop = NULL, *skip = NULL;
 1655     int         n = 0;
 1656     char       *t;
 1657 
 1658     if (*chptr->chname != '#')
 1659         return;
 1660 
 1661     *modebuf = *parabuf = '\0';
 1662     channel_modes(cptr, modebuf, parabuf, chptr);
 1663 
 1664     ircsprintf(buf, ":%s SJOIN %ld %s %s %s :", me.name,
 1665                chptr->channelts, chptr->chname, modebuf, parabuf);
 1666     t = buf + strlen(buf);
 1667     for (l = chptr->members; l; l = l->next)
 1668         if (l->flags & MODE_CHANOP)
 1669         {
 1670             anop = l;
 1671             break;
 1672         }
 1673     /*
 1674      * follow the channel, but doing anop first if it's defined *
 1675      * -orabidoo
 1676      */
 1677     l = NULL;
 1678     for (;;)
 1679     {
 1680         if (anop)
 1681         {
 1682             l = skip = anop;
 1683             anop = NULL;
 1684         }
 1685         else
 1686         {
 1687             if (l == NULL || l == skip)
 1688                 l = chptr->members;
 1689             else
 1690                 l = l->next;
 1691             if (l && l == skip)
 1692                 l = l->next;
 1693             if (l == NULL)
 1694                 break;
 1695         }
 1696         if (l->flags & MODE_CHANOP)
 1697             *t++ = '@';
 1698 #ifdef USE_HALFOPS
 1699         if (l->flags & CHFL_HALFOP)
 1700             *t++ = '%';
 1701 #endif
 1702         if (l->flags & MODE_VOICE)
 1703             *t++ = '+';
 1704         strcpy(t, l->cptr->name);
 1705         t += strlen(t);
 1706         *t++ = ' ';
 1707         n++;
 1708         if (t - buf > BUFSIZE - 80)
 1709         {
 1710             *t++ = '\0';
 1711             if (t[-1] == ' ')
 1712                 t[-1] = '\0';
 1713             sendto_one(cptr, "%s", buf);
 1714             sprintf(buf, ":%s SJOIN %ld %s 0 :", me.name,
 1715                     chptr->channelts, chptr->chname);
 1716             t = buf + strlen(buf);
 1717             n = 0;
 1718         }
 1719     }
 1720 
 1721     if (n)
 1722     {
 1723         *t++ = '\0';
 1724         if (t[-1] == ' ')
 1725             t[-1] = '\0';
 1726         sendto_one(cptr, "%s", buf);
 1727     }
 1728     *parabuf = '\0';
 1729     *modebuf = '+';
 1730     modebuf[1] = '\0';
 1731     send_channel_lists(cptr, chptr);
 1732     if (modebuf[1] || *parabuf)
 1733         sendto_one(cptr, ":%s MODE %s %ld %s %s",
 1734                 me.name, chptr->chname, chptr->channelts, modebuf, parabuf);
 1735 }
 1736 
 1737 /* m_mode parv[0] - sender parv[1] - channel */
 1738 
 1739 int m_mode(aClient *cptr, aClient *sptr, int parc, char *parv[])
 1740 {
 1741     int         mcount = 0, chanop=0;
 1742     aChannel   *chptr;
 1743     int subparc = 2;
 1744     
 1745     /* Now, try to find the channel in question */
 1746     if (parc > 1)
 1747     {
 1748         chptr = find_channel(parv[1], NullChn);
 1749         if (chptr == NullChn)
 1750             return m_umode(cptr, sptr, parc, parv);
 1751     }
 1752     else
 1753     {
 1754         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
 1755                    me.name, parv[0], "MODE");
 1756         return 0;
 1757     }
 1758     
 1759     if (!check_channelname(sptr, (unsigned char *) parv[1]))
 1760         return 0;
 1761 
 1762     if (MyClient(sptr))
 1763     {
 1764         if (is_chan_op(sptr, chptr))
 1765             chanop = 1;
 1766     }
 1767     else
 1768         chanop = 2;
 1769         
 1770     if (parc < 3)
 1771     {
 1772         *modebuf = *parabuf = '\0';
 1773         modebuf[1] = '\0';
 1774         channel_modes(sptr, modebuf, parabuf, chptr);
 1775         sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0],
 1776                    chptr->chname, modebuf, parabuf);
 1777         sendto_one(sptr, rpl_str(RPL_CREATIONTIME), me.name, parv[0],
 1778                    chptr->chname, chptr->channelts);
 1779         return 0;
 1780     }
 1781 
 1782     if(IsServer(cptr) && IsDigit(parv[2][0]))
 1783     {
 1784         ts_val modets = atol(parv[2]);
 1785         if(modets != 0 && (modets > chptr->channelts))
 1786             return 0;
 1787         subparc++;
 1788     }
 1789 
 1790     mcount = set_mode(cptr, sptr, chptr, chanop, parc - subparc, parv + subparc,
 1791                       modebuf, parabuf);
 1792 
 1793     if (strlen(modebuf) > (size_t) 1)
 1794         switch (mcount)
 1795         {
 1796             case 0:
 1797                 break;
 1798             case -1:
 1799                 if (MyClient(sptr))
 1800                     sendto_one(sptr,
 1801                            err_str(ERR_CHANOPRIVSNEEDED),
 1802                            me.name, parv[0], chptr->chname);
 1803                 else
 1804                     ircstp->is_fake++;
 1805                 break;
 1806             default:
 1807                 if(chptr->mode.mode & MODE_AUDITORIUM)
 1808                     sendto_channelopvoice_butserv_me(chptr, sptr,
 1809                                           ":%s MODE %s %s %s", parv[0],
 1810                                           chptr->chname, modebuf,
 1811                                           parabuf);
 1812                 else
 1813                     sendto_channel_butserv_me(chptr, sptr,
 1814                                           ":%s MODE %s %s %s", parv[0],
 1815                                           chptr->chname, modebuf,
 1816                                           parabuf);
 1817                 sendto_serv_butone(cptr, ":%s MODE %s %ld %s %s", parv[0],
 1818                                    chptr->chname, chptr->channelts, modebuf,
 1819                                    parabuf);
 1820         }
 1821     return 0;
 1822 }
 1823 
 1824 /* the old set_mode was pissing me off with it's disgusting
 1825  * hackery, so I rewrote it.  Hope this works. }:> --wd
 1826  * Corrected a 4-year-old mistake: the max modes limit applies to
 1827  * the number of parameters, not mode changes. -Quension [Apr 2004]
 1828  */
 1829 static int set_mode(aClient *cptr, aClient *sptr, aChannel *chptr,
 1830                     int level, int parc, char *parv[], char *mbuf, char *pbuf) 
 1831 {
 1832 #define SM_ERR_NOPRIVS 0x0001 /* is not an op */
 1833 #define SM_ERR_MOREPARMS 0x0002 /* needs more parameters */     
 1834 #define SM_ERR_RESTRICTED 0x0004 /* not allowed to op others or be op'd */      
 1835 #define SM_ERR_NOTOPER    0x0008 /* not an irc op */
 1836 #define SM_MAXMODES MAXMODEPARAMSUSER
 1837 
 1838 /* this macro appends to pbuf */
 1839 #define ADD_PARA(p) pptr = p; if(pidx) pbuf[pidx++] = ' '; while(*pptr) \
 1840                     pbuf[pidx++] = *pptr++;
 1841     
 1842     static int flags[] = 
 1843     {
 1844         MODE_PRIVATE, 'p', MODE_SECRET, 's',
 1845         MODE_MODERATED, 'm', MODE_NOPRIVMSGS, 'n',
 1846         MODE_TOPICLIMIT, 't', MODE_REGONLY, 'R',
 1847         MODE_INVITEONLY, 'i', MODE_NOCTRL, 'c', MODE_OPERONLY, 'O',
 1848         MODE_MODREG, 'M', MODE_SSLONLY, 'S', MODE_AUDITORIUM, 'A',
 1849 #ifdef SPAMFILTER
 1850         MODE_PRIVACY, 'P',
 1851 #endif
 1852 #ifdef USE_CHANMODE_L
 1853         MODE_LISTED, 'L',
 1854 #endif
 1855         0x0, 0x0
 1856     };
 1857     
 1858     Link *lp; /* for walking lists */
 1859     chanMember *cm; /* for walking channel member lists */
 1860     aBan *bp; /* for walking banlists */
 1861     char *modes=parv[0]; /* user's idea of mode changes */
 1862     int args; /* counter for what argument we're on */
 1863     int anylistsent = IsServer(sptr) ? 1 : 0; /* Only send 1 list and not to servers */
 1864     char change='+'; /* by default we + things... */
 1865     int errors=0; /*
 1866                    * errors returned, set with bitflags
 1867                    * so we only return them once
 1868                    */
 1869     /* from remote servers, ungodly numbers of modes can be sent, but
 1870      * from local users only SM_MAXMODES are allowed */
 1871     int maxparams=((IsServer(sptr) || IsULine(sptr)) ? 512 : SM_MAXMODES);
 1872     int nmodes=0; /* how many modes we've set so far */
 1873     int nparams=0; /* how many modes with parameters we've set so far */
 1874     aClient *who = NULL; /* who we're doing a mode for */
 1875     int chasing = 0;
 1876     int i=0;
 1877     char moreparmsstr[]="MODE   ";
 1878     char nuhbuf[NICKLEN + USERLEN + HOSTLEN + 6]; /* for bans */
 1879     char tmp[128]; /* temporary buffer */
 1880     int pidx = 0; /* index into pbuf */
 1881     char *pptr; /* temporary paramater pointer */
 1882     char *morig = mbuf; /* beginning of mbuf */
 1883     /* :cptr-name MODE chptr->chname [MBUF] [PBUF] (buflen - 3 max and NULL) */
 1884     /* added another 11 bytes to this, for TSMODE -epi */
 1885     int prelen = strlen(cptr->name) + strlen(chptr->chname) + 27;
 1886     /* drop duplicates in the same mode change -- yeah, this is cheap, but real
 1887        duplicate checking will have to wait for a protocol change to kill
 1888        desyncs */
 1889     int seenalready = 0;
 1890 
 1891 
 1892     args=1;
 1893         
 1894     if(parc<1)
 1895         return 0;
 1896 
 1897     *mbuf++='+'; /* add the plus, even if they don't */
 1898     /* go through once to clean the user's mode string so we can
 1899      * have a simple parser run through it...*/
 1900 
 1901     while(*modes) 
 1902     {
 1903         switch(*modes) 
 1904         {
 1905         case '+':
 1906             if(*(mbuf-1)=='-') 
 1907             {
 1908                 *(mbuf-1)='+'; /* change it around now */
 1909                 change='+';
 1910                 break;
 1911             }
 1912             else if(change=='+') /* we're still doing a +, we don't care */
 1913                 break;
 1914             change=*modes;
 1915             *mbuf++='+';
 1916             break;
 1917 
 1918         case '-':
 1919             if(*(mbuf-1)=='+') 
 1920             {
 1921                 *(mbuf-1)='-'; /* change it around now */
 1922                 change='-';
 1923                 break;
 1924             }
 1925             else if(change=='-')
 1926                 break; /* we're still doing a -, we don't care */
 1927             change=*modes;
 1928             *mbuf++='-';
 1929             break;
 1930 
 1931         case 'O':
 1932             if (level<1)
 1933             {
 1934                 errors |= SM_ERR_NOPRIVS;
 1935                 break;
 1936             }
 1937             else if (MyClient(sptr) && !IsOper(sptr))
 1938             {
 1939                 errors |= SM_ERR_NOTOPER;
 1940                 break;
 1941             } 
 1942             else 
 1943             {
 1944                 if (change=='+')
 1945                     chptr->mode.mode|=MODE_OPERONLY;
 1946                 else
 1947                     chptr->mode.mode&=~MODE_OPERONLY;
 1948                 *mbuf++ = *modes;
 1949                 nmodes++;
 1950             }
 1951             break;
 1952         case 'o':
 1953 #ifdef USE_HALFOPS
 1954         case 'h':
 1955 #endif
 1956         case 'v':
 1957             if(level<1) 
 1958             {
 1959                 errors |= SM_ERR_NOPRIVS;
 1960                 break;
 1961             }
 1962             if(parv[args]==NULL)
 1963             {
 1964                 /* silently drop the spare +o/v's */
 1965                 break;
 1966             }
 1967             if(++nparams > maxparams)
 1968             {
 1969                 /* too many modes with params, eat this one */
 1970                 args++;
 1971                 break;
 1972             }
 1973                         
 1974             who = find_chasing(sptr, parv[args], &chasing);
 1975             cm = find_user_member(chptr->members, who);
 1976             if(cm == NULL) 
 1977             {
 1978                 sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
 1979                            me.name, cptr->name, parv[args], chptr->chname);
 1980                 /* swallow the arg */
 1981                 args++;
 1982                 break;
 1983             }
 1984             /* if we're going to overflow our mode buffer,
 1985              * drop the change instead */
 1986             if((prelen + (mbuf - morig) + pidx + NICKLEN + 1) > 
 1987                REALMODEBUFLEN) 
 1988             {
 1989                 args++;
 1990                 break;
 1991             }
 1992             
 1993 #ifdef NO_LOCAL_CMODE_h
 1994             if(*modes=='h' && MyClient(sptr))
 1995             {
 1996                 sendto_one(sptr,":%s NOTICE %s :*** Notice -- Half-ops are not fully supported yet.",
 1997                            me.name, sptr->name);
 1998                 args++;
 1999                 break;
 2000             }
 2001 #endif
 2002 
 2003             /* if we have the user, set them +/-[vo] */
 2004             if(change=='+')
 2005             {
 2006                 int resend_nicklist = (chptr->mode.mode & MODE_AUDITORIUM) && MyClient(who) && !((cm->flags & CHFL_CHANOP) || (cm->flags & CHFL_HALFOP) || (cm->flags & CHFL_VOICE));
 2007                 switch(*modes)
 2008                 {
 2009                     case 'o': cm->flags|= CHFL_CHANOP; break;
 2010 #ifdef USE_HALFOPS
 2011                     case 'h': cm->flags|= CHFL_HALFOP; break;
 2012 #endif
 2013                     case 'v': cm->flags|= CHFL_VOICE; break;
 2014                 }
 2015                 if (resend_nicklist)
 2016                 {
 2017                     char *fake_parv[3];
 2018 
 2019                     sendto_one(who, ":%s KICK %s %s :%s",
 2020                                me.name, chptr->chname, who->name, "Resending nicklist...");
 2021                     sendto_prefix_one(who, who, ":%s JOIN :%s", who->name, chptr->chname);
 2022 
 2023                     if(chptr->topic[0] != '\0')
 2024                     {
 2025                         sendto_one(who, rpl_str(RPL_TOPIC), me.name, who->name,
 2026                                    chptr->chname, chptr->topic);
 2027                         sendto_one(who, rpl_str(RPL_TOPICWHOTIME), me.name, who->name,
 2028                                    chptr->chname, chptr->topic_nick, chptr->topic_time);
 2029                     }
 2030 
 2031                     fake_parv[0] = who->name;
 2032                     fake_parv[1] = chptr->chname;
 2033                     fake_parv[2] = NULL;
 2034 
 2035                     m_names(who, who, 2, fake_parv);
 2036                 }
 2037                 if(chptr->mode.mode & MODE_AUDITORIUM) sendto_channel_butserv_noopvoice(chptr, who, ":%s JOIN :%s", who->name, chptr->chname);
 2038             }
 2039             else
 2040             {
 2041                 switch(*modes)
 2042                 {
 2043                     case 'o': cm->flags&=~CHFL_CHANOP; break;
 2044 #ifdef USE_HALFOPS
 2045                     case 'h': cm->flags&=~CHFL_HALFOP; break;
 2046 #endif
 2047                     case 'v': cm->flags&=~CHFL_VOICE; break;
 2048                 }
 2049                 if(chptr->mode.mode & MODE_AUDITORIUM) sendto_channel_butserv_noopvoice(chptr, who, PartFmt, who->name, chptr->chname);
 2050             }
 2051             
 2052             /* we've decided their mode was okay, cool */
 2053             *mbuf++ = *modes;
 2054             ADD_PARA(cm->cptr->name)
 2055                 args++;
 2056             nmodes++;
 2057             if (IsServer(sptr) && *modes == 'o' && change=='+') 
 2058             {
 2059                 chptr->channelts = 0;
 2060                 sendto_ops("Server %s setting +o and blasting TS on %s",
 2061                            sptr->name, chptr->chname);
 2062             }
 2063             break;
 2064 
 2065 #ifdef INVITE_LISTS
 2066         case 'I':
 2067             if (level < 1 && parv[args] != NULL)
 2068             {
 2069                 errors |= SM_ERR_NOPRIVS;
 2070                 break;
 2071             }
 2072             else if (parv[args] == NULL)
 2073             {
 2074                 anInvite    *invite;
 2075 
 2076                 if (anylistsent) /* don't send the list if they have received one */
 2077                     break;
 2078 
 2079                 if((chptr->xflags & XFLAG_HIDE_MODE_LISTS) && !IsAnOper(sptr) && !is_chan_op(sptr,chptr))
 2080                 {
 2081                     if(chptr->xflags & XFLAG_USER_VERBOSE)
 2082                         verbose_to_relaychan(sptr, chptr, "mode(+I)", NULL);
 2083                     if(chptr->xflags & XFLAG_OPER_VERBOSE)
 2084                         verbose_to_opers(sptr, chptr, "mode(+I)", NULL);
 2085                     sendto_one(sptr, rpl_str(RPL_ENDOFINVITELIST), me.name,
 2086                                sptr->name, chptr->chname);
 2087                     anylistsent = 1;
 2088                     break;
 2089                 }
 2090 
 2091                 for (invite = chptr->invite_list; invite; invite = invite->next)
 2092                     sendto_one(sptr, rpl_str(RPL_INVITELIST), me.name, cptr->name,
 2093                                chptr->chname, invite->invstr, invite->who, invite->when);
 2094                 sendto_one(cptr, rpl_str(RPL_ENDOFINVITELIST), me.name,
 2095                            cptr->name, chptr->chname);
 2096                 anylistsent = 1;
 2097                 break;
 2098             }
 2099             if(++nparams > maxparams)
 2100             {
 2101                 /* too many modes with params, eat this one */
 2102                 args++;
 2103                 break;
 2104             }
 2105             
 2106             if (*parv[args] == ':' || *parv[args] == '\0')
 2107             {
 2108                 args++; 
 2109                 break;
 2110             }
 2111 
 2112 #ifdef NO_LOCAL_CIDR_CHANNELBANS
 2113             if(MyClient(sptr) && strchr(parv[args],'/'))
 2114             {
 2115                 sendto_one(sptr,":%s NOTICE %s :*** Notice -- CIDR channel bans/invites/exempts are not supported yet.",
 2116                            me.name, sptr->name);
 2117                 args++;
 2118                 break;
 2119             }
 2120 #endif
 2121 
 2122             strcpy(nuhbuf, collapse(pretty_mask(parv[args])));
 2123             parv[args] = nuhbuf;
 2124             /* if we're going to overflow our mode buffer,
 2125              * drop the change instead */
 2126             if((prelen + (mbuf - morig) + pidx + strlen(nuhbuf) + 1) > 
 2127                REALMODEBUFLEN) 
 2128             {
 2129                 args++;
 2130                 break;
 2131             }
 2132             /* if we can't add or delete (depending) the ban, change is
 2133              * worthless anyhow */
 2134             
 2135             if(!(change=='+' && !add_invite_id(sptr, chptr, parv[args])) && 
 2136                !(change=='-' && !del_invite_id(chptr, parv[args])))
 2137             {
 2138                 args++;
 2139                 break;
 2140             }
 2141             
 2142             *mbuf++ = 'I';
 2143             ADD_PARA(parv[args])
 2144                 args++;
 2145             nmodes++;
 2146             break;
 2147 #endif
 2148 
 2149 #ifdef EXEMPT_LISTS
 2150         case 'e':
 2151             if (level < 1 && parv[args] != NULL)
 2152             {
 2153                 errors |= SM_ERR_NOPRIVS;
 2154                 break;
 2155             }
 2156             else if (parv[args] == NULL)
 2157             {
 2158                 aBanExempt*    exempt;
 2159                 
 2160                 if (anylistsent) /* don't send the list if they have received one */
 2161                     break;
 2162                 if((chptr->xflags & XFLAG_HIDE_MODE_LISTS) && !IsAnOper(sptr) && !is_chan_op(sptr,chptr))
 2163                 {
 2164                     if(chptr->xflags & XFLAG_USER_VERBOSE)
 2165                         verbose_to_relaychan(sptr, chptr, "mode(+e)", NULL);
 2166                     if(chptr->xflags & XFLAG_OPER_VERBOSE)
 2167                         verbose_to_opers(sptr, chptr, "mode(+e)", NULL);
 2168                     sendto_one(sptr, rpl_str(RPL_ENDOFEXEMPTLIST), me.name,
 2169                                sptr->name, chptr->chname);
 2170                     anylistsent = 1;
 2171                     break;
 2172                 }
 2173                 for (exempt = chptr->banexempt_list; exempt; exempt = exempt->next)
 2174                     sendto_one(sptr, rpl_str(RPL_EXEMPTLIST), me.name, cptr->name,
 2175                                chptr->chname, exempt->banstr, exempt->who, exempt->when);
 2176                 sendto_one(cptr, rpl_str(RPL_ENDOFEXEMPTLIST), me.name,
 2177                            cptr->name, chptr->chname);
 2178                 anylistsent = 1;
 2179                 break;
 2180             }
 2181             if(++nparams > maxparams)
 2182             {
 2183                 /* too many modes with params, eat this one */
 2184                 args++;
 2185                 break;
 2186             }
 2187             
 2188             if (*parv[args] == ':' || *parv[args] == '\0')
 2189             {
 2190                 args++; 
 2191                 break;
 2192             }
 2193 
 2194 #ifdef NO_LOCAL_CIDR_CHANNELBANS
 2195             if(MyClient(sptr) && strchr(parv[args],'/'))
 2196             {
 2197                 sendto_one(sptr,":%s NOTICE %s :*** Notice -- CIDR channel bans/invites/exempts are not supported yet.",
 2198                            me.name, sptr->name);
 2199                 args++;
 2200                 break;
 2201             }
 2202 #endif
 2203 
 2204             strcpy(nuhbuf, collapse(pretty_mask(parv[args])));
 2205             parv[args] = nuhbuf;
 2206             /* if we're going to overflow our mode buffer,
 2207              * drop the change instead */
 2208             if((prelen + (mbuf - morig) + pidx + strlen(nuhbuf) + 1) > 
 2209                REALMODEBUFLEN) 
 2210             {
 2211                 args++;
 2212                 break;
 2213             }
 2214             /* if we can't add or delete (depending) the exempt, change is
 2215              * worthless anyhow */
 2216             
 2217             if(!(change=='+' && !add_exempt_id(sptr, chptr, parv[args])) && 
 2218                !(change=='-' && !del_exempt_id(chptr, parv[args])))
 2219             {
 2220                 args++;
 2221                 break;
 2222             }
 2223 
 2224             *mbuf++ = 'e';
 2225             ADD_PARA(parv[args])
 2226                 args++;
 2227             nmodes++;
 2228             break;
 2229 #endif
 2230     
 2231         case 'b':
 2232             /* if the user has no more arguments, then they just want
 2233              * to see the bans, okay, cool. */
 2234             if(level < 1 && parv[args] != NULL)
 2235             {
 2236                 errors |= SM_ERR_NOPRIVS;
 2237                 break;
 2238             }
 2239             /* show them the bans, woowoo */
 2240             if(parv[args]==NULL)
 2241             {
 2242                 if (anylistsent)
 2243                     break;
 2244                 if((chptr->xflags & XFLAG_HIDE_MODE_LISTS) && !IsAnOper(sptr) && !is_chan_op(sptr,chptr))
 2245                 {
 2246                     if(chptr->xflags & XFLAG_USER_VERBOSE)
 2247                         verbose_to_relaychan(sptr, chptr, "mode(+b)", NULL);
 2248                     if(chptr->xflags & XFLAG_OPER_VERBOSE)
 2249                         verbose_to_opers(sptr, chptr, "mode(+b)", NULL);
 2250                     sendto_one(sptr, rpl_str(RPL_ENDOFBANLIST), me.name,
 2251                                sptr->name, chptr->chname);
 2252                     anylistsent = 1;
 2253                     break;
 2254                 }
 2255                 for(bp=chptr->banlist;bp;bp=bp->next)
 2256                     sendto_one(sptr, rpl_str(RPL_BANLIST), me.name, cptr->name,
 2257                                chptr->chname, bp->banstr, bp->who, bp->when);
 2258                 sendto_one(cptr, rpl_str(RPL_ENDOFBANLIST), me.name,
 2259                            cptr->name, chptr->chname);
 2260                 anylistsent = 1;
 2261                 break; /* we don't pass this along, either.. */
 2262             }
 2263             if(++nparams > maxparams)
 2264             {
 2265                 /* too many modes with params, eat this one */
 2266                 args++;
 2267                 break;
 2268             }
 2269             
 2270             /* do not allow : in bans, or a null ban */
 2271             if(*parv[args]==':' || *parv[args] == '\0') 
 2272             {
 2273                 args++;
 2274                 break;
 2275             }
 2276 
 2277 #ifdef NO_LOCAL_CIDR_CHANNELBANS
 2278             if(MyClient(sptr) && strchr(parv[args],'/'))
 2279             {
 2280                 sendto_one(sptr,":%s NOTICE %s :*** Notice -- CIDR channel bans/invites/exempts are not supported yet.",
 2281                            me.name, sptr->name);
 2282                 args++;
 2283                 break;
 2284             }
 2285 #endif
 2286 
 2287             /* make a 'pretty' ban mask here, then try and set it */
 2288             /* okay kids, let's do this again.
 2289              * the buffer returned by pretty_mask is from 
 2290              * make_nick_user_host. This buffer is eaten by add/del banid.
 2291              * Thus, some poor schmuck gets himself on the banlist.
 2292              * Fixed. - lucas */
 2293             strcpy(nuhbuf, collapse(pretty_mask(parv[args])));
 2294             parv[args] = nuhbuf;
 2295             /* if we're going to overflow our mode buffer,
 2296              * drop the change instead */
 2297             if((prelen + (mbuf - morig) + pidx + strlen(nuhbuf) + 1) > 
 2298                REALMODEBUFLEN) 
 2299             {
 2300                 args++;
 2301                 break;
 2302             }
 2303             /* if we can't add or delete (depending) the ban, change is
 2304              * worthless anyhow */
 2305             
 2306             if(!(change=='+' && !add_banid(sptr, chptr, parv[args])) && 
 2307                !(change=='-' && !del_banid(chptr, parv[args])))
 2308             {
 2309                 args++;
 2310                 break;
 2311             }
 2312             
 2313             *mbuf++ = 'b';
 2314             ADD_PARA(parv[args])
 2315                 args++;
 2316             nmodes++;
 2317             break;
 2318 
 2319         case 'j':
 2320 #ifdef JOINRATE_SERVER_ONLY
 2321             if (MyClient(sptr)) 
 2322             {
 2323                 sendto_one(sptr, err_str(ERR_ONLYSERVERSCANCHANGE),
 2324                            me.name, cptr->name, chptr->chname);
 2325                 break;
 2326             }
 2327 #endif
 2328 
 2329             if(level<1) 
 2330             {
 2331                 errors |= SM_ERR_NOPRIVS;
 2332                 break;
 2333             }
 2334 
 2335             /* if it's a -, just change the flag, we have no arguments */
 2336             if(change=='-')
 2337             {
 2338                 if (MyClient(sptr) && (seenalready & MODE_JOINRATE))
 2339                     break;
 2340                 seenalready |= MODE_JOINRATE;
 2341 
 2342                 if((prelen + (mbuf - morig) + pidx + 1) > REALMODEBUFLEN) 
 2343                     break;
 2344                 *mbuf++ = 'j';
 2345                 chptr->mode.mode &= ~MODE_JOINRATE;
 2346                 chptr->mode.jr_num = DEFAULT_JOIN_NUM;
 2347                 chptr->mode.jr_time = DEFAULT_JOIN_TIME;
 2348                 chptr->mode.jrl_size = DEFAULT_JOIN_SIZE;
 2349                 chptr->jrl_bucket = 0;
 2350                 chptr->jrl_last = NOW;  /* slow start */
 2351                 nmodes++;
 2352                 break;
 2353             }
 2354             else 
 2355             {
 2356                 char *tmpa, *tmperr;
 2357                 int j_num, j_time, tval;
 2358 
 2359                 if(parv[args] == NULL) 
 2360                 {
 2361                     errors|=SM_ERR_MOREPARMS;
 2362                     break;
 2363                 }
 2364                 if(++nparams > maxparams)
 2365                 {
 2366                     /* too many modes with params, eat this one */
 2367                     args++;
 2368                     break;
 2369                 }
 2370                 if (MyClient(sptr) && (seenalready & MODE_JOINRATE))
 2371                 {
 2372                     args++;
 2373                     break;
 2374                 }
 2375                 seenalready |= MODE_JOINRATE;
 2376 
 2377                 tmpa = strchr(parv[args], ':');
 2378                 if(tmpa)
 2379                 {
 2380                     *tmpa = '\0';
 2381                     tmpa++;
 2382                     j_time = strtol(tmpa, &tmperr, 10);
 2383                     if(*tmperr != '\0' || j_time < 0)
 2384                     {
 2385                         /* error, user specified something 
 2386                          * invalid, just bail. */
 2387                         args++;
 2388                         break;
 2389                     }
 2390                 }
 2391                 else
 2392                     j_time = 0;
 2393 
 2394                 j_num = strtol(parv[args], &tmperr, 10);
 2395                 if(*tmperr != '\0' || j_num < 0)
 2396                 {
 2397                     args++;
 2398                     break;
 2399                 }
 2400                 
 2401                 /* safety cap */
 2402                 if (j_num > 127)
 2403                     j_num = 127;
 2404                 if (j_time > 127)
 2405                     j_time = 127;
 2406 
 2407                 /* range limit for local non-samodes */
 2408                 if (MyClient(sptr) && level < 2)
 2409                 {
 2410                     /* static limits: time <= 60, 2 <= num <= 20 */
 2411                     if (j_time > 60)
 2412                         j_time = 60;
 2413                     if (j_num > 20)
 2414                         j_num = 20;
 2415                     if (j_num < 2)
 2416                         j_num = 2;
 2417 
 2418                     /* adjust number to time using min rate 1/8 */
 2419                     tval = (j_time-1)/8+1;
 2420                     if (j_num < tval)
 2421                         j_num = tval;
 2422 
 2423                     /* adjust time to number using max rate 2/1 */
 2424                     tval = j_num/2;
 2425                     if (j_time < tval)
 2426                         j_time = tval;
 2427                 }
 2428 
 2429                 if(j_num == 0 || j_time == 0)
 2430                 {
 2431                     j_num = j_time = 0;
 2432                     ircsprintf(tmp, "0");
 2433                 }
 2434                 else
 2435                     ircsprintf(tmp, "%d:%d", j_num, j_time);
 2436 
 2437                 /* if we're going to overflow our mode buffer,
 2438                  * drop the change instead */
 2439                 if((prelen + (mbuf - morig) + pidx + strlen(tmp)) > REALMODEBUFLEN) 
 2440                 {
 2441                     args++;
 2442                     break;
 2443                 }
 2444 
 2445                 chptr->mode.mode |= MODE_JOINRATE;
 2446                 chptr->mode.jr_num = j_num;
 2447                 chptr->mode.jr_time = j_time;
 2448                 chptr->mode.jrl_size = j_num * j_time;
 2449                 chptr->jrl_bucket = 0;
 2450                 chptr->jrl_last = NOW;  /* slow start */
 2451                 *mbuf++ = 'j';
 2452                 ADD_PARA(tmp);
 2453                 args++;
 2454                 nmodes++;
 2455                 break;
 2456             }
 2457 
 2458         case 'l':
 2459             if(level<1) 
 2460             {
 2461                 errors |= SM_ERR_NOPRIVS;
 2462                 break;
 2463             }
 2464 
 2465             /* if it's a -, just change the flag, we have no arguments */
 2466             if(change=='-')
 2467             {
 2468                 if (MyClient(sptr) && (seenalready & MODE_LIMIT))
 2469                     break;
 2470                 seenalready |= MODE_LIMIT;
 2471 
 2472                 if((prelen + (mbuf - morig) + pidx + 1) > REALMODEBUFLEN) 
 2473                     break;
 2474                 *mbuf++ = 'l';
 2475                 chptr->mode.mode &= ~MODE_LIMIT;
 2476                 chptr->mode.limit = 0;
 2477                 nmodes++;
 2478                 break;
 2479             }
 2480             else 
 2481             {
 2482                 if(parv[args] == NULL) 
 2483                 {
 2484                     errors|=SM_ERR_MOREPARMS;
 2485                     break;
 2486                 }
 2487                 if(++nparams > maxparams)
 2488                 {
 2489                     /* too many modes with params, eat this one */
 2490                     args++;
 2491                     break;
 2492                 }
 2493                 if (MyClient(sptr) && (seenalready & MODE_LIMIT))
 2494                 {
 2495                     args++;
 2496                     break;
 2497                 }
 2498                 seenalready |= MODE_LIMIT;
 2499 
 2500                 /* if we're going to overflow our mode buffer,
 2501                  * drop the change instead */
 2502                 if((prelen + (mbuf - morig) + pidx + 16) > REALMODEBUFLEN) 
 2503                 {
 2504                     args++;
 2505                     break;
 2506                 }
 2507                
 2508                 i = atoi(parv[args]);
 2509 
 2510                 /* toss out invalid modes */
 2511                 if(i < 1)
 2512                 {
 2513                     args++;
 2514                     break;
 2515                 }
 2516                 ircsprintf(tmp, "%d", i);
 2517                 chptr->mode.limit = i;
 2518                 chptr->mode.mode |= MODE_LIMIT;
 2519                 *mbuf++ = 'l';
 2520                 ADD_PARA(tmp);
 2521                 args++;
 2522                 nmodes++;
 2523                 break;
 2524             }
 2525 
 2526         case 'k':
 2527             if(level<1) 
 2528             {
 2529                 errors |= SM_ERR_NOPRIVS;
 2530                 break;
 2531             }
 2532             if(parv[args]==NULL)
 2533                 break;
 2534             if(++nparams > maxparams)
 2535             {
 2536                 /* too many modes with params, eat this one */
 2537                 args++;
 2538                 break;
 2539             }
 2540             if (MyClient(sptr) && (seenalready & MODE_KEY))
 2541             {
 2542                 args++;
 2543                 break;
 2544             }
 2545             seenalready |= MODE_KEY;
 2546 
 2547             /* do not allow keys to start with :! ack! - lucas */
 2548             /* another ack: don't let people set null keys! */
 2549             /* and yet a third ack: no spaces in keys -epi  */
 2550             if(*parv[args]==':' || *parv[args] == '\0' ||
 2551                strchr(parv[args], ' '))
 2552             {
 2553                 args++;
 2554                 break;
 2555             }
 2556             
 2557             /* Do not let *'s in keys in preperation for key hiding - Raist
 2558              * Also take out ",", which makes a channel unjoinable - lucas
 2559              */
 2560             
 2561             if (strchr(parv[args], '*') != NULL || 
 2562                 strchr(parv[args], ',') != NULL) 
 2563             {
 2564                 args++;
 2565                 break;
 2566             }
 2567             
 2568             /* if we're going to overflow our mode buffer,
 2569              * drop the change instead */
 2570             if((prelen + (mbuf - morig) + pidx + KEYLEN+2) > REALMODEBUFLEN) 
 2571             {
 2572                 args++;
 2573                 break;
 2574             }
 2575             
 2576             /* if they're an op, they can futz with the key in
 2577              * any manner they like, we're not picky */
 2578             if(change=='+') 
 2579             {
 2580                 strncpy(chptr->mode.key,parv[args],KEYLEN);
 2581                 ADD_PARA(chptr->mode.key)
 2582             }
 2583             else 
 2584             {
 2585                 char *sendkey = chptr->mode.key;
 2586                 if (!*sendkey)
 2587                     sendkey = parv[args];
 2588                 ADD_PARA(sendkey)
 2589                 *chptr->mode.key = '\0';
 2590             }
 2591             *mbuf++='k';
 2592             args++;
 2593             nmodes++;
 2594             break;
 2595 
 2596         case 'r':
 2597             if (MyClient(sptr) && (seenalready & MODE_REGISTERED))
 2598                 break;
 2599             seenalready |= MODE_REGISTERED;
 2600             if (!IsServer(sptr) && !IsULine(sptr)) 
 2601             {
 2602                 sendto_one(sptr, err_str(ERR_ONLYSERVERSCANCHANGE),
 2603                            me.name, cptr->name, chptr->chname);
 2604                 break;
 2605             }
 2606             else 
 2607             {
 2608                 if((prelen + (mbuf - morig) + pidx + 1) > REALMODEBUFLEN) 
 2609                     break;
 2610                 
 2611                 if(change=='+')
 2612                     chptr->mode.mode|=MODE_REGISTERED;
 2613                 else
 2614                     chptr->mode.mode&=~MODE_REGISTERED;
 2615             }
 2616             *mbuf++='r';
 2617             nmodes++;
 2618             break;
 2619 
 2620         case 'A':
 2621             if (MyClient(sptr) && (seenalready & MODE_AUDITORIUM))
 2622                 break;
 2623             seenalready |= MODE_AUDITORIUM;
 2624             if (MyClient(sptr))
 2625             {
 2626                 sendto_one(sptr, err_str(ERR_ONLYSERVERSCANCHANGE),
 2627                            me.name, cptr->name, chptr->chname);
 2628                 break;
 2629             }
 2630             else
 2631             {       
 2632                 if((prelen + (mbuf - morig) + pidx + 1) > REALMODEBUFLEN)
 2633                     break;
 2634              
 2635                 if(change=='+')
 2636                     chptr->mode.mode|=MODE_AUDITORIUM;
 2637                 else
 2638                     chptr->mode.mode&=~MODE_AUDITORIUM;
 2639             }
 2640             *mbuf++='A';
 2641             nmodes++;
 2642             break;
 2643 
 2644         case 'L':
 2645             if (MyClient(sptr) && (seenalready & MODE_LISTED))
 2646                 break;
 2647             seenalready |= MODE_LISTED;
 2648             if (MyClient(sptr))
 2649             {
 2650                 sendto_one(sptr, err_str(ERR_ONLYSERVERSCANCHANGE),
 2651                            me.name, cptr->name, chptr->chname);
 2652                 break;
 2653             }
 2654             else
 2655             {       
 2656                 if((prelen + (mbuf - morig) + pidx + 1) > REALMODEBUFLEN)
 2657                     break;
 2658              
 2659                 if(change=='+')
 2660                     chptr->mode.mode|=MODE_LISTED;
 2661                 else
 2662                     chptr->mode.mode&=~MODE_LISTED;
 2663             }
 2664             *mbuf++='L';
 2665             nmodes++;
 2666             break;
 2667             
 2668         case 'i':
 2669             if(level < 1) 
 2670             {
 2671                 errors |= SM_ERR_NOPRIVS;
 2672                 break;
 2673             }
 2674             if(change=='-')
 2675                 while ((lp=chptr->invites))
 2676                     del_invite(lp->value.cptr, chptr);
 2677             /* fall through to default case */
 2678 
 2679         default:
 2680             /* phew, no more tough modes. }:>, the rest are all
 2681              * covered in one step 
 2682              * with the above array */
 2683             if(level<1) 
 2684             {
 2685                 errors |= SM_ERR_NOPRIVS;
 2686                 break;
 2687             }
 2688             for(i=1;flags[i]!=0x0;i+=2) 
 2689             {
 2690                 if((prelen + (mbuf - morig) + pidx + 1) > REALMODEBUFLEN) 
 2691                     break;
 2692                 
 2693                 if(*modes==(char)flags[i]) 
 2694                 {
 2695                     if (MyClient(sptr) && (seenalready & flags[i-1]))
 2696                         break;
 2697                     seenalready |= flags[i-1];
 2698                     
 2699                     if(change=='+')
 2700                         chptr->mode.mode |= flags[i-1];
 2701                     else
 2702                         chptr->mode.mode &= ~flags[i-1];
 2703                     *mbuf++=*modes;
 2704                     nmodes++;
 2705                     break;
 2706                 }
 2707             }
 2708             /* unknown mode.. */
 2709             if(flags[i]==0x0) 
 2710             {
 2711                 /* we still spew lots of unknown mode bits...*/
 2712                 /* but only to our own clients, silently ignore bogosity
 2713                  * from other servers... */
 2714                 if(MyClient(sptr))
 2715                     sendto_one(sptr, err_str(ERR_UNKNOWNMODE), me.name,
 2716                                sptr->name, *modes);
 2717                         
 2718             }
 2719             break;
 2720         }
 2721         
 2722         /* spit out more parameters error here */
 2723         if(errors & SM_ERR_MOREPARMS && MyClient(sptr)) 
 2724         {
 2725             moreparmsstr[5]=change;
 2726             moreparmsstr[6]=*modes;
 2727             sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name,
 2728                        sptr->name, moreparmsstr);
 2729             errors &= ~SM_ERR_MOREPARMS; /* oops, kill it in this case */
 2730         }
 2731         modes++;
 2732     }
 2733     /* clean up the end of the string... */
 2734     if(*(mbuf-1) == '+' || *(mbuf-1) == '-')
 2735         *(mbuf-1) = '\0';
 2736     else
 2737         *mbuf = '\0';
 2738     pbuf[pidx] = '\0';
 2739     if(MyClient(sptr)) 
 2740     {
 2741         if(errors & SM_ERR_NOPRIVS)
 2742             sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name,
 2743                        sptr->name, chptr->chname);        
 2744         if(errors & SM_ERR_NOTOPER)
 2745             sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
 2746         if(errors & SM_ERR_RESTRICTED)
 2747             sendto_one(sptr,":%s NOTICE %s :*** Notice -- You are "
 2748                        "restricted and cannot chanop others",
 2749                        me.name, sptr->name);
 2750     }
 2751     /* all done! */
 2752     return nmodes;
 2753 #undef ADD_PARA
 2754 }
 2755 
 2756 static int can_join(aClient *sptr, aChannel *chptr, char *key)
 2757 {
 2758     Link   *lp;
 2759     int invited = 0;
 2760     int error = 0;
 2761     int jrl = 0;
 2762     char *r = NULL;
 2763 
 2764     for(lp = sptr->user->invited; lp; lp = lp->next)
 2765     {
 2766         if(lp->value.chptr == chptr)
 2767         {
 2768             invited = 1;
 2769             break;
 2770         }
 2771     }
 2772 
 2773     if (invited)
 2774         return 1;
 2775     
 2776     joinrate_prejoin(chptr);
 2777 
 2778     if (chptr->join_connect_time && (sptr->firsttime + chptr->join_connect_time > NOW) && !is_xflags_exempted(sptr,chptr))
 2779     {
 2780         r = "+X";
 2781         error = ERR_NEEDTOWAIT;
 2782     }
 2783     else if (chptr->mode.mode & MODE_INVITEONLY)
 2784     {
 2785         r = "+i";
 2786         error = ERR_INVITEONLYCHAN;
 2787     }
 2788     else if (chptr->mode.mode & MODE_OPERONLY && !IsOper(sptr))
 2789     {
 2790         r = "+O";
 2791         error = ERR_INVITEONLYCHAN;
 2792     }
 2793     else if (chptr->mode.limit && chptr->users >= chptr->mode.limit)
 2794     {
 2795         r = "+l";
 2796         error = ERR_CHANNELISFULL;
 2797     }
 2798     else if (chptr->mode.mode & MODE_SSLONLY && !IsSSL(sptr))
 2799     {
 2800         r = "+S";
 2801         error = ERR_NOSSL;
 2802     }
 2803     else if (chptr->mode.mode & MODE_REGONLY && !IsRegNick(sptr))
 2804     {
 2805         r = "+R"; /* Only needed for verbose_to_*() */
 2806         error = ERR_NEEDREGGEDNICK;
 2807     }
 2808     else if (*chptr->mode.key && (BadPtr(key) || mycmp(chptr->mode.key, key)))
 2809     {
 2810         r = "+k"; /* Only needed for verbose_to_*() */
 2811         error = ERR_BADCHANNELKEY;
 2812     }
 2813     else if (!joinrate_check(chptr, sptr, 1))
 2814     {
 2815         r = "+j";
 2816         error = ERR_CHANNELISFULL;
 2817         jrl = 1;
 2818     }
 2819 
 2820 #ifdef INVITE_LISTS
 2821     if (error && !jrl && is_invited(sptr, chptr) && (error!=ERR_NEEDTOWAIT || (chptr->xflags & XFLAG_EXEMPT_INVITES)))
 2822         error = 0;
 2823 #endif
 2824 
 2825     if (!error && is_banned(sptr, chptr, NULL))
 2826     {
 2827         r = "+b"; /* Only needed for verbose_to_*() */
 2828         error = ERR_BANNEDFROMCHAN;
 2829     }
 2830 
 2831     if (error)
 2832     {
 2833         if (!jrl)
 2834             joinrate_warn(chptr, sptr);
 2835 
 2836         if(error==ERR_NEEDTOWAIT)
 2837         {
 2838             sendto_one(sptr,":%s NOTICE %s :*** Notice -- You must wait %ld seconds before you will be able to join %s", me.name, sptr->name, (sptr->firsttime + chptr->join_connect_time - NOW), chptr->chname);
 2839             /* Let's also fake a nice reject message most clients will recognize -Kobi. */
 2840             if(chptr->xflags & XFLAG_EXEMPT_REGISTERED)
 2841                 error = ERR_NEEDREGGEDNICK;
 2842             else
 2843                 error = ERR_INVITEONLYCHAN;
 2844             if(chptr->xflags & XFLAG_USER_VERBOSE)
 2845                 verbose_to_relaychan(sptr, chptr, "join", "xflag_join_connect_time");
 2846             if(chptr->xflags & XFLAG_OPER_VERBOSE)
 2847                 verbose_to_opers(sptr, chptr, "join", "xflag_join_connect_time");
 2848         }
 2849         else
 2850         {
 2851             if(chptr->xflags & XFLAG_USER_VERBOSE) verbose_to_relaychan(sptr, chptr, "join", r);
 2852             if(!jrl && (chptr->xflags & XFLAG_OPER_VERBOSE)) verbose_to_opers(sptr, chptr, "join", r);
 2853         }
 2854 
 2855         if (error==ERR_NEEDREGGEDNICK)
 2856             sendto_one(sptr, getreply(ERR_NEEDREGGEDNICK), me.name, sptr->name,
 2857                        chptr->chname, "join", chptr->chname, aliastab[AII_NS].nick,
 2858                        aliastab[AII_NS].server, NS_Register_URL);
 2859         else
 2860             sendto_one(sptr, getreply(error), me.name, sptr->name,
 2861                        chptr->chname, r);
 2862         return 0;
 2863     }
 2864 
 2865     return 1;
 2866 }
 2867 
 2868 /*
 2869  * can_join_whynot:
 2870  * puts a list of the modes preventing us from joining in reasonbuf
 2871  * ret is number of matched modes
 2872  */
 2873 static int 
 2874 can_join_whynot(aClient *sptr, aChannel *chptr, char *key, char *reasonbuf)
 2875 {
 2876     Link   *lp;
 2877     int invited = 0;
 2878     int rbufpos = 0;
 2879 
 2880     for(lp = sptr->user->invited; lp; lp = lp->next) 
 2881     {
 2882         if(lp->value.chptr == chptr) 
 2883         {
 2884             invited = 1;
 2885             break;
 2886         }
 2887     }
 2888 
 2889     if (invited)
 2890         return 0;
 2891     
 2892     joinrate_prejoin(chptr);
 2893 
 2894     if (chptr->mode.mode & MODE_INVITEONLY)
 2895         reasonbuf[rbufpos++] = 'i';
 2896     if (chptr->mode.mode & MODE_REGONLY && !IsRegNick(sptr))
 2897         reasonbuf[rbufpos++] = 'R';
 2898     if (chptr->mode.mode & MODE_OPERONLY && !IsOper(sptr))
 2899         reasonbuf[rbufpos++] = 'O';
 2900     if (*chptr->mode.key && (BadPtr(key) || mycmp(chptr->mode.key, key)))
 2901         reasonbuf[rbufpos++] = 'k';
 2902     if (chptr->mode.limit && chptr->users >= chptr->mode.limit) 
 2903         reasonbuf[rbufpos++] = 'l';
 2904     if (!joinrate_check(chptr, sptr, 0))
 2905         reasonbuf[rbufpos++] = 'j';
 2906 
 2907 #ifdef INVITE_LISTS
 2908     if (rbufpos && is_invited(sptr, chptr))
 2909         rbufpos = 0;
 2910 #endif
 2911 
 2912     if (is_banned(sptr, chptr, NULL))
 2913         reasonbuf[rbufpos++] = 'b';
 2914 
 2915     reasonbuf[rbufpos] = '\0';
 2916     return rbufpos;
 2917 }
 2918 
 2919 /*
 2920  * Remove bells and commas from channel name
 2921  */
 2922 void clean_channelname(unsigned char *cn)
 2923 {
 2924     for (; *cn; cn++)
 2925         /*
 2926          * All characters >33 are allowed, except commas, and the weird
 2927          * fake-space character mIRCers whine about -wd
 2928          */
 2929         if (*cn < 33 || *cn == ',' || (*cn == 160))
 2930         {
 2931             *cn = '\0';
 2932             return;
 2933         }
 2934     return;
 2935 }
 2936 
 2937 /* we also tell the client if the channel is invalid. */
 2938 int check_channelname(aClient *cptr, unsigned char *cn)
 2939 {
 2940     if(!MyClient(cptr))
 2941         return 1;
 2942     for(;*cn;cn++) 
 2943     {
 2944         if(*cn<33 || *cn == ',' || *cn==160) 
 2945         {
 2946             sendto_one(cptr, getreply(ERR_BADCHANNAME), me.name, cptr->name,
 2947                        cn);
 2948             return 0;
 2949         }
 2950     }
 2951     return 1;
 2952 }
 2953 
 2954 /*
 2955  * *  Get Channel block for chname (and allocate a new channel *
 2956  * block, if it didn't exist before).
 2957  */
 2958 aChannel *
 2959 get_channel(aClient *cptr, char *chname, int flag, int *created)
 2960 {
 2961     aChannel *chptr;
 2962     int         len;
 2963 
 2964     if(created)
 2965         *created = 0;
 2966 
 2967     if (BadPtr(chname))
 2968         return NULL;
 2969 
 2970     len = strlen(chname);
 2971     if (MyClient(cptr) && len > CHANNELLEN)
 2972     {
 2973         len = CHANNELLEN;
 2974         *(chname + CHANNELLEN) = '\0';
 2975     }
 2976     if ((chptr = find_channel(chname, (aChannel *) NULL)))
 2977         return (chptr);
 2978     if (flag == CREATE)
 2979     {
 2980         chptr = make_channel();
 2981 
 2982         if(created)
 2983             *created = 1;
 2984         
 2985         strncpyzt(chptr->chname, chname, len + 1);
 2986         if (channel)
 2987             channel->prevch = chptr;
 2988         chptr->prevch = NULL;
 2989         chptr->nextch = channel;
 2990         channel = chptr;
 2991         chptr->channelts = timeofday;
 2992         chptr->max_bans = MAXBANS;
 2993         chptr->max_invites = MAXINVITELIST;
 2994         (void) add_to_channel_hash_table(chname, chptr);
 2995         Count.chan++;
 2996     }
 2997     return chptr;
 2998 }
 2999 
 3000 static void add_invite(aClient *cptr, aChannel *chptr)
 3001 {
 3002     Link   *inv, **tmp;
 3003     
 3004     del_invite(cptr, chptr);
 3005     /*
 3006      * delete last link in chain if the list is max length
 3007      */
 3008     if (list_length(cptr->user->invited) >= maxchannelsperuser)
 3009     {
 3010         /*
 3011          * This forgets the channel side of invitation     -Vesa inv =
 3012          * cptr->user->invited; cptr->user->invited = inv->next;
 3013          * free_link(inv);
 3014          */
 3015         del_invite(cptr, cptr->user->invited->value.chptr);
 3016         
 3017     }
 3018     
 3019     /*
 3020      * add client to channel invite list
 3021      */
 3022     inv = make_link();
 3023     inv->value.cptr = cptr;
 3024     inv->next = chptr->invites;
 3025     chptr->invites = inv;
 3026     /*
 3027      * add channel to the end of the client invite list
 3028      */
 3029     for (tmp = &(cptr->user->invited); *tmp; tmp = &((*tmp)->next));
 3030     inv = make_link();
 3031     inv->value.chptr = chptr;
 3032     inv->next = NULL;
 3033     (*tmp) = inv;
 3034 }
 3035 
 3036 /*
 3037  * Delete Invite block from channel invite list and client invite list
 3038  */
 3039 void del_invite(aClient *cptr, aChannel *chptr)
 3040 {
 3041     Link  **inv, *tmp;
 3042 
 3043     for (inv = &(chptr->invites); (tmp = *inv); inv = &tmp->next)
 3044         if (tmp->value.cptr == cptr)
 3045         {
 3046             *inv = tmp->next;
 3047             free_link(tmp);
 3048             break;
 3049         }
 3050     
 3051     for (inv = &(cptr->user->invited); (tmp = *inv); inv = &tmp->next)
 3052         if (tmp->value.chptr == chptr)
 3053         {
 3054             *inv = tmp->next;
 3055             free_link(tmp);
 3056             break;
 3057         }
 3058 }
 3059 
 3060 /*
 3061  * *  Subtract one user from channel i (and free channel *  block, if
 3062  * channel became empty).
 3063  */
 3064 static void sub1_from_channel(aChannel *chptr)
 3065 {
 3066     Link   *tmp;
 3067     aBan              *bp, *bprem;
 3068 #ifdef INVITE_LISTS
 3069     anInvite          *invite, *invrem;
 3070 #endif
 3071 #ifdef EXEMPT_LISTS
 3072     aBanExempt        *exempt, *exrem;
 3073 #endif
 3074     
 3075     if (--chptr->users <= 0) 
 3076     {
 3077         /*
 3078          * Now, find all invite links from channel structure
 3079          */
 3080         while ((tmp = chptr->invites))
 3081             del_invite(tmp->value.cptr, chptr);
 3082 
 3083         bp = chptr->banlist;
 3084         while (bp)
 3085         {
 3086             bprem = bp;
 3087             bp = bp->next;
 3088             MyFree(bprem->banstr);
 3089             MyFree(bprem->who);
 3090             MyFree(bprem);
 3091         }
 3092 #ifdef INVITE_LISTS
 3093         invite = chptr->invite_list;
 3094         while (invite)
 3095      {
 3096             invrem = invite;
 3097             invite = invite->next;
 3098             MyFree(invrem->invstr);
 3099             MyFree(invrem->who);
 3100             MyFree(invrem);
 3101         }
 3102 #endif
 3103 #ifdef EXEMPT_LISTS
 3104         exempt = chptr->banexempt_list;
 3105         while (exempt)
 3106         {
 3107             exrem = exempt;
 3108             exempt = exempt->next;
 3109             MyFree(exrem->banstr);
 3110             MyFree(exrem->who);
 3111             MyFree(exrem);
 3112         }
 3113 #endif
 3114 
 3115         if (chptr->prevch)
 3116             chptr->prevch->nextch = chptr->nextch;
 3117         else
 3118             channel = chptr->nextch;
 3119         if (chptr->nextch)
 3120             chptr->nextch->prevch = chptr->prevch;
 3121         (void) del_from_channel_hash_table(chptr->chname, chptr);
 3122 #ifdef FLUD
 3123         free_fluders(NULL, chptr);
 3124 #endif
 3125         if(chptr->greetmsg) MyFree(chptr->greetmsg);
 3126         free_channel(chptr);
 3127         Count.chan--;
 3128     }
 3129 }
 3130 
 3131 /* Check if a services join request should be sent to services and send it if needed... -Kobi.
 3132    Returns:
 3133     0 = Success (sent the request to services)
 3134     1 = Failure (didn't send the request to services)
 3135  */
 3136 int send_sjr_to_services(aClient *sptr, char *chname, char *key)
 3137 {
 3138     aChannel *chptr = find_channel(chname, NULL);
 3139     int is_invited = 0;
 3140     Link *lp;
 3141 
 3142     if(chptr)
 3143     {
 3144         if(!(chptr->xflags & XFLAG_SJR) && services_jr!=2) return 1; /* Channel isn't xflagged, let the local server handle the request
 3145                                                                         (unless sjr is enabled for all channels [services_jr==2]) */
 3146         for(lp = sptr->user->invited; lp; lp = lp->next)
 3147         {
 3148             if(lp->value.chptr == chptr)
 3149             {
 3150                 is_invited = 1;
 3151                 break;
 3152             }
 3153         }
 3154     }
 3155     else if(services_jr!=2) return 1; /* Channel doesn't exist (so it can't be xflagged) */
 3156 
 3157     if(!aliastab[AII_NS].client)
 3158         return 1; /* Services are off-line, let the local server handle the request */
 3159 
 3160     if(key)
 3161         sendto_one(aliastab[AII_NS].client->from, ":%s SJR %d %s :%s", sptr->name,
 3162                    is_invited, chname, key);
 3163     else
 3164         sendto_one(aliastab[AII_NS].client->from, ":%s SJR %d %s", sptr->name,
 3165                    is_invited, chname);
 3166 
 3167     return 0;
 3168 }
 3169 
 3170 /*
 3171  * m_join 
 3172  * parv[0] = sender prefix
 3173  * parv[1] = channel
 3174  * parv[2] = channel password (key)
 3175  */
 3176 int m_join(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3177 {
 3178     static char jbuf[BUFSIZE];
 3179     Link   *lp;
 3180     struct simBan *ban;
 3181     aChannel *chptr;
 3182     char   *name, *key = NULL;
 3183     int         i, flags = 0, chanlen=0;        
 3184     int         allow_op = YES;
 3185     char       *p = NULL, *p2 = NULL;
 3186         
 3187 #ifdef ANTI_SPAMBOT
 3188     int         successful_join_count = 0;      
 3189     /* Number of channels successfully joined */
 3190 #endif
 3191         
 3192     if (!(sptr->user))
 3193     {
 3194         /* something is *fucked* - bail */
 3195         return 0;
 3196     }
 3197         
 3198     if (parc < 2 || *parv[1] == '\0')
 3199     {
 3200         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
 3201                    me.name, parv[0], "JOIN");
 3202         return 0;
 3203     }
 3204 
 3205     if (MyClient(sptr))
 3206         parv[1] = canonize(parv[1]);
 3207         
 3208     *jbuf = '\0';
 3209     /*
 3210      * * Rebuild list of channels joined to be the actual result of the *
 3211      * JOIN.  Note that "JOIN 0" is the destructive problem.
 3212      */
 3213     for (i = 0, name = strtoken(&p, parv[1], ","); name;
 3214          name = strtoken(&p, (char *) NULL, ","))
 3215     {
 3216         /*
 3217          * pathological case only on longest channel name. * If not dealt
 3218          * with here, causes desynced channel ops * since ChannelExists()
 3219          * doesn't see the same channel * as one being joined. cute bug.
 3220          * Oct 11 1997, Dianora/comstud
 3221          */
 3222         if(!check_channelname(sptr, (unsigned char *) name))
 3223             continue;
 3224         
 3225         chanlen=strlen(name);
 3226         
 3227         if (chanlen > CHANNELLEN) /* same thing is done in get_channel() */
 3228         {
 3229             name[CHANNELLEN] = '\0';
 3230             chanlen=CHANNELLEN;
 3231         }
 3232         if (*name == '0' && !atoi(name))
 3233             *jbuf = '\0';
 3234         else if (!IsChannelName(name))
 3235         {
 3236             if (MyClient(sptr))
 3237                 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
 3238                            me.name, parv[0], name);
 3239             continue;
 3240         }
 3241         if (*jbuf)
 3242             (void) strcat(jbuf, ",");
 3243         (void) strncat(jbuf, name, sizeof(jbuf) - i - 1);
 3244         i += chanlen + 1;
 3245     }
 3246     
 3247     p = NULL;
 3248     if (parv[2])
 3249         key = strtoken(&p2, parv[2], ",");
 3250     parv[2] = NULL;             /*
 3251                                  * for m_names call later, parv[parc]
 3252                                  * * must == NULL 
 3253                                  */
 3254     for (name = strtoken(&p, jbuf, ","); name;
 3255          key = (key) ? strtoken(&p2, NULL, ",") : NULL,
 3256              name = strtoken(&p, NULL, ","))
 3257     {
 3258         /*
 3259          * JOIN 0 sends out a part for all channels a user * has
 3260          * joined.
 3261          */
 3262         if (*name == '0' && !atoi(name))
 3263         {
 3264             if (sptr->user->channel == NULL)
 3265                 continue;
 3266             while ((lp = sptr->user->channel))
 3267             {
 3268                 chptr = lp->value.chptr;
 3269                 sendto_channel_butserv(chptr, sptr, PartFmt,
 3270                                        parv[0], chptr->chname);
 3271                 remove_user_from_channel(sptr, chptr);
 3272             }
 3273             /*
 3274              * Added /quote set for SPAMBOT
 3275              * 
 3276              * int spam_time = MIN_JOIN_LEAVE_TIME; int spam_num =
 3277              * MAX_JOIN_LEAVE_COUNT;
 3278              */
 3279 #ifdef ANTI_SPAMBOT             /* Dianora */
 3280                         
 3281             if (MyConnect(sptr) && !IsAnOper(sptr))
 3282             {
 3283                 if (sptr->join_leave_count >= spam_num)
 3284                 {
 3285                     if(call_hooks(CHOOK_SPAMWARN, sptr, 2, spam_num, NULL) != FLUSH_BUFFER)
 3286                         sendto_realops_lev(SPAM_LEV, "User %s (%s@%s) is a "
 3287                                        "possible spambot", sptr->name,
 3288                                        sptr->user->username, sptr->user->host);
 3289                     sptr->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
 3290                 }
 3291                 else
 3292                 {
 3293                     int         t_delta;
 3294                     
 3295                     if ((t_delta = (NOW - sptr->last_leave_time)) >
 3296                         JOIN_LEAVE_COUNT_EXPIRE_TIME)
 3297                     {
 3298                         int         decrement_count;
 3299                         
 3300                         decrement_count = (t_delta /
 3301                                            JOIN_LEAVE_COUNT_EXPIRE_TIME);
 3302                         
 3303                         if (decrement_count > sptr->join_leave_count)
 3304                             sptr->join_leave_count = 0;
 3305                         else
 3306                             sptr->join_leave_count -= decrement_count;
 3307                     }
 3308                     else
 3309                     {
 3310                         if ((NOW - (sptr->last_join_time)) < spam_time)
 3311                         {
 3312                             /* oh, its a possible spambot */
 3313                             sptr->join_leave_count++;
 3314                         }
 3315                     }
 3316                     sptr->last_leave_time = NOW;
 3317                 }
 3318             }
 3319 #endif
 3320             sendto_serv_butone(cptr, ":%s JOIN 0", parv[0]);
 3321             continue;
 3322         }
 3323         
 3324         if (MyConnect(sptr))
 3325         {
 3326             /* have we quarantined this channel? */
 3327             if(!IsOper(sptr) && (ban = check_mask_simbanned(name, SBAN_CHAN)))
 3328             {
 3329                 sendto_one(sptr, getreply(ERR_CHANBANREASON), me.name, parv[0], name,
 3330                         BadPtr(ban->reason) ? "Reserved channel" :      
 3331                         ban->reason);
 3332                 if (call_hooks(CHOOK_FORBID, cptr, name, ban) != FLUSH_BUFFER)
 3333                     sendto_realops_lev(REJ_LEV,
 3334                                        "Forbidding restricted channel %s from %s",
 3335                                        name, get_client_name(cptr, FALSE));
 3336                 continue;
 3337             }
 3338 
 3339             /*
 3340              * local client is first to enter previously nonexistent *
 3341              * channel so make them (rightfully) the Channel * Operator.
 3342              */
 3343             flags = (ChannelExists(name)) ? 0 : CHFL_CHANOP;
 3344 
 3345             if (!IsAnOper(sptr) && server_was_split
 3346                 && !(confopts & FLAGS_SPLITOPOK))
 3347                     allow_op = NO;
 3348             
 3349             if ((sptr->user->joined >= maxchannelsperuser) &&
 3350                 (!IsAnOper(sptr) || (sptr->user->joined >= 
 3351                                      maxchannelsperuser * 3)))
 3352             {
 3353                 sendto_one(sptr, err_str(ERR_TOOMANYCHANNELS),
 3354                            me.name, parv[0], name);
 3355 #ifdef ANTI_SPAMBOT
 3356                 if (successful_join_count)
 3357                     sptr->last_join_time = NOW;
 3358 #endif
 3359                 return 0;
 3360             }
 3361 #ifdef ANTI_SPAMBOT             /*
 3362                                  * Dianora 
 3363                                  */
 3364             if (flags == 0)     /* if channel doesn't exist, don't penalize */
 3365                 successful_join_count++;
 3366             if (sptr->join_leave_count >= spam_num)
 3367             {
 3368                                 /* Its already known as a possible spambot */
 3369                 
 3370                 if (sptr->oper_warn_count_down > 0)  /* my general paranoia */
 3371                     sptr->oper_warn_count_down--;
 3372                 else
 3373                     sptr->oper_warn_count_down = 0;
 3374                 
 3375                 if (sptr->oper_warn_count_down == 0)
 3376                 {
 3377                     if(call_hooks(CHOOK_SPAMWARN, sptr, 3, spam_num, name) != FLUSH_BUFFER)
 3378                         sendto_realops_lev(SPAM_LEV, "User %s (%s@%s) trying to "
 3379                                        "join %s is a possible spambot",
 3380                                        sptr->name,
 3381                                        sptr->user->username,
 3382                                        sptr->user->host,
 3383                                        name);
 3384                     sptr->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
 3385                 }
 3386 # ifndef ANTI_SPAMBOT_WARN_ONLY
 3387                 return 0;               /* Don't actually JOIN anything, but
 3388                                          * don't let spambot know that */
 3389 # endif
 3390             }
 3391 #endif
 3392         }
 3393         else
 3394         {
 3395             /*
 3396              * complain for remote JOINs to existing channels * (they
 3397              * should be SJOINs) -orabidoo
 3398              */
 3399             if (!ChannelExists(name))
 3400                 ts_warn("User on %s remotely JOINing new channel",
 3401                         sptr->user->server);
 3402         }
 3403 
 3404         if(services_jr && send_sjr_to_services(sptr, name, key)==0)
 3405             continue;
 3406 
 3407         chptr = get_channel(sptr, name, CREATE, NULL);
 3408 
 3409         if (chptr && IsMember(sptr, chptr))
 3410             continue;
 3411 
 3412         if (call_hooks(CHOOK_JOIN, sptr, chptr) == FLUSH_BUFFER)
 3413             continue; /* Let modules reject JOINs */
 3414 
 3415         
 3416         if (!chptr || (MyConnect(sptr) && !can_join(sptr, chptr, key)))
 3417         {
 3418 #ifdef ANTI_SPAMBOT
 3419             if (successful_join_count > 0)
 3420                 successful_join_count--;
 3421 #endif
 3422             continue;
 3423         }
 3424         
 3425 /* only complain when the user can join the channel, the channel is
 3426  * being created by this user, and this user is not allowed to be an op.
 3427  * - lucas 
 3428  */
 3429 
 3430         if (flags && !allow_op)
 3431             sendto_one(sptr, ":%s NOTICE %s :*** Notice -- Due to a network "
 3432                        "split, you can not obtain channel operator status in "
 3433                        "a new channel at this time.", me.name, sptr->name);
 3434         
 3435         /* Complete user entry to the new channel (if any) */
 3436         if (allow_op)
 3437             add_user_to_channel(chptr, sptr, flags);
 3438         else
 3439             add_user_to_channel(chptr, sptr, 0);
 3440         joinrate_dojoin(chptr, sptr);
 3441         /* Set timestamp if appropriate, and propagate */
 3442         if (MyClient(sptr) && flags == CHFL_CHANOP) 
 3443         {
 3444             chptr->channelts = timeofday;
 3445             
 3446             /* we keep channel "creations" to the server sjoin format,
 3447                so we can bounce modes and stuff if our ts is older. */
 3448             
 3449             if (allow_op)
 3450                 sendto_serv_butone(cptr, ":%s SJOIN %ld %s + :@%s", me.name,
 3451                                    chptr->channelts, name, parv[0]);
 3452             else
 3453                 sendto_serv_butone(cptr, ":%s SJOIN %ld %s + :%s", me.name,
 3454                                    chptr->channelts, name, parv[0]);
 3455         }
 3456         else if (MyClient(sptr)) 
 3457             sendto_serv_butone(cptr, CliSJOINFmt, parv[0], chptr->channelts,
 3458                                name);
 3459         else 
 3460             sendto_serv_butone(cptr, ":%s JOIN :%s", parv[0], name);
 3461 
 3462         /* notify all other users on the new channel */
 3463         sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
 3464                 
 3465         if (MyClient(sptr)) 
 3466         {
 3467             del_invite(sptr, chptr);
 3468             if (chptr->topic[0] != '\0') 
 3469             {
 3470                 sendto_one(sptr, rpl_str(RPL_TOPIC), me.name,
 3471                            parv[0], name, chptr->topic);
 3472                 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME),
 3473                            me.name, parv[0], name,
 3474                            chptr->topic_nick,
 3475                            chptr->topic_time);
 3476             }
 3477             parv[1] = name;
 3478             (void) m_names(cptr, sptr, 2, parv);
 3479             if(chptr->greetmsg)
 3480             {
 3481                 sendto_one(sptr, ":%s!%s@%s PRIVMSG %s :%s", Network_Name, Network_Name, DEFAULT_STAFF_ADDRESS, name, chptr->greetmsg);
 3482             }
 3483         }
 3484     }
 3485         
 3486 #ifdef ANTI_SPAMBOT
 3487     if (MyConnect(sptr) && successful_join_count)
 3488         sptr->last_join_time = NOW;
 3489 #endif
 3490     return 0;
 3491 }
 3492 
 3493 /* m_sajoin
 3494  * join a channel regardless of modes.
 3495  */
 3496 
 3497 int m_sajoin(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3498 {
 3499         aChannel        *chptr;
 3500         char            *name;
 3501         int              i;
 3502         char            errmodebuf[128];
 3503 
 3504         /* Remote sajoin? nope. */
 3505         if(!MyClient(sptr))
 3506                 return 0;
 3507 
 3508         if(!IsSAdmin(sptr))
 3509         {
 3510                 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
 3511                 return 0;
 3512         }
 3513 
 3514         if (parc < 2 || *parv[1] == '\0')
 3515         {
 3516                 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
 3517                            me.name, parv[0], "SAJOIN");
 3518                 return 0;
 3519         }
 3520 
 3521         name = parv[1];
 3522 
 3523         chptr = find_channel(name, NULL);
 3524         if(!chptr)
 3525         {
 3526                 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
 3527                            me.name, parv[0], name);
 3528                 return 0;
 3529         }
 3530 
 3531         /* bail if they're already in the channel */
 3532         if(IsMember(sptr, chptr))
 3533                 return 0;
 3534 
 3535         if((i = can_join_whynot(sptr, chptr, NULL, errmodebuf)))
 3536         {
 3537             send_globops("from %s: %s used SAJOIN (%s +%s)",
 3538                          me.name, sptr->name, chptr->chname, errmodebuf);
 3539             sendto_serv_butone(NULL, ":%s GLOBOPS :%s used SAJOIN (%s +%s)",
 3540                                me.name, sptr->name, chptr->chname, errmodebuf);
 3541         }
 3542         else
 3543             sendto_one(sptr, ":%s NOTICE %s :You didn't need to use"
 3544                        " /SAJOIN for %s", me.name, parv[0], chptr->chname);
 3545 
 3546         add_user_to_channel(chptr, sptr, 0);
 3547         sendto_serv_butone(cptr, CliSJOINFmt, parv[0], chptr->channelts, name);
 3548         sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name);
 3549         if(MyClient(sptr))
 3550         {
 3551             if(chptr->topic[0] != '\0')
 3552             {
 3553                 sendto_one(sptr, rpl_str(RPL_TOPIC), me.name, parv[0], 
 3554                             name, chptr->topic);
 3555                 sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0], 
 3556                             name, chptr->topic_nick, chptr->topic_time);
 3557             }
 3558             parv[1] = name;
 3559             parv[2] = NULL;
 3560             m_names(cptr, sptr, 2, parv);
 3561         }
 3562         return 0;
 3563 }
 3564 
 3565 /*
 3566  * m_part 
 3567  * parv[0] = sender prefix 
 3568  * parv[1] = channel
 3569  * parv[2] = Optional part reason
 3570  */
 3571 int m_part(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3572 {
 3573     aChannel *chptr;
 3574     char       *p, *name;
 3575     char *reason = (parc > 2 && parv[2]) ? parv[2] : NULL;
 3576 
 3577     if (parc < 2 || parv[1][0] == '\0')
 3578     {
 3579         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
 3580                    me.name, parv[0], "PART");
 3581         return 0;
 3582     }
 3583     
 3584     name = strtoken(&p, parv[1], ",");
 3585     
 3586 #ifdef ANTI_SPAMBOT             /* Dianora */
 3587     /* if its my client, and isn't an oper */
 3588     
 3589     if (name && MyConnect(sptr) && !IsAnOper(sptr))
 3590     {
 3591         if (sptr->join_leave_count >= spam_num)
 3592         {
 3593             if(call_hooks(CHOOK_SPAMWARN, sptr, 4, spam_num, NULL) != FLUSH_BUFFER)
 3594                 sendto_realops_lev(SPAM_LEV, "User %s (%s@%s) is a possible"
 3595                             " spambot", sptr->name, sptr->user->username, 
 3596                             sptr->user->host);
 3597             sptr->oper_warn_count_down = OPER_SPAM_COUNTDOWN;
 3598         }
 3599         else
 3600         {
 3601             int         t_delta;
 3602 
 3603             if ((t_delta = (NOW - sptr->last_leave_time)) >
 3604                 JOIN_LEAVE_COUNT_EXPIRE_TIME)
 3605             {
 3606                 int         decrement_count;
 3607 
 3608                 decrement_count = (t_delta / JOIN_LEAVE_COUNT_EXPIRE_TIME);
 3609 
 3610                 if (decrement_count > sptr->join_leave_count)
 3611                     sptr->join_leave_count = 0;
 3612                 else
 3613                     sptr->join_leave_count -= decrement_count;
 3614             }
 3615             else
 3616             {
 3617                 if ((NOW - (sptr->last_join_time)) < spam_time)
 3618                 {
 3619                     /* oh, its a possible spambot */
 3620                     sptr->join_leave_count++;
 3621                 }
 3622             }
 3623             sptr->last_leave_time = NOW;
 3624         }
 3625     }
 3626 #endif
 3627 
 3628     while (name)
 3629     {
 3630         chptr = get_channel(sptr, name, 0, NULL);
 3631         if (!chptr)
 3632         {
 3633             sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
 3634                        me.name, parv[0], name);
 3635             name = strtoken(&p, (char *) NULL, ",");
 3636             continue;
 3637         }
 3638 
 3639         if (!IsMember(sptr, chptr))
 3640         {
 3641             sendto_one(sptr, err_str(ERR_NOTONCHANNEL),
 3642                        me.name, parv[0], name);
 3643             name = strtoken(&p, (char *) NULL, ",");
 3644             continue;
 3645         }
 3646 
 3647 #ifdef SPAMFILTER
 3648         if(MyClient(sptr) && reason && !(chptr->mode.mode & MODE_PRIVACY) && check_sf(sptr, reason, "part", SF_CMD_PART, chptr->chname))
 3649             return FLUSH_BUFFER;
 3650 #endif
 3651 
 3652         /* Remove user from the old channel (if any) */
 3653 
 3654         if (parc < 3 || can_send(sptr,chptr,reason) || IsSquelch(sptr) || ((chptr->xflags & XFLAG_NO_PART_MSG) && !is_xflags_exempted(sptr,chptr)))
 3655         {
 3656             if(reason && *reason && (chptr->xflags & XFLAG_USER_VERBOSE))
 3657                 verbose_to_relaychan(sptr, chptr, "part_msg", reason);
 3658             if(reason && *reason && (chptr->xflags & XFLAG_OPER_VERBOSE))
 3659                 verbose_to_opers(sptr, chptr, "part_msg", reason);
 3660             sendto_serv_butone(cptr, PartFmt, parv[0], name);
 3661             sendto_channel_butserv(chptr, sptr, PartFmt, parv[0], name);
 3662         }
 3663         else
 3664         {
 3665             sendto_serv_butone(cptr, PartFmt2, parv[0], name, reason);
 3666             sendto_channel_butserv(chptr, sptr, PartFmt2, parv[0], name,
 3667                                    reason);
 3668         }
 3669         remove_user_from_channel(sptr, chptr);
 3670         name = strtoken(&p, (char *) NULL, ",");
 3671     }
 3672     return 0;
 3673 }
 3674 
 3675 /*
 3676  * m_kick
 3677  * parv[0] = sender prefix
 3678  * parv[1] = channel
 3679  * parv[2] = client to kick
 3680  * parv[3] = kick comment
 3681  */
 3682 int m_kick(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3683 {
 3684     aClient    *who;
 3685     aChannel   *chptr;
 3686     int         chasing = 0;
 3687     int         user_count;     /* count nicks being kicked, only allow 4 */
 3688     char       *comment, *name, *p = NULL, *user, *p2 = NULL;
 3689     int        cankick = 0;
 3690 
 3691     if (parc < 3 || *parv[1] == '\0')
 3692     {
 3693         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
 3694                    me.name, parv[0], "KICK");
 3695         return 0;
 3696     }
 3697     if (IsServer(sptr) && !IsULine(sptr))
 3698         sendto_ops("KICK from %s for %s %s",
 3699                    parv[0], parv[1], parv[2]);
 3700     comment = (BadPtr(parv[3])) ? parv[0] : parv[3];
 3701     if (strlen(comment) > (size_t) TOPICLEN)
 3702         comment[TOPICLEN] = '\0';
 3703     
 3704     *nickbuf = *buf = '\0';
 3705     name = strtoken(&p, parv[1], ",");
 3706     
 3707     while (name)
 3708     {
 3709         chptr = get_channel(sptr, name, !CREATE, NULL);
 3710         if (!chptr)
 3711         {
 3712             sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
 3713                        me.name, parv[0], name);
 3714             name = strtoken(&p, (char *) NULL, ",");
 3715             continue;
 3716         }
 3717 
 3718         /*
 3719          * You either have chan op privs, or you don't -Dianora 
 3720          *
 3721          * orabidoo and I discussed this one for a while... I hope he
 3722          * approves of this code, users can get quite confused...
 3723          * -Dianora
 3724          */
 3725 
 3726         if (!IsServer(sptr) && !(cankick = is_chan_cankick(sptr, chptr)) && !IsULine(sptr))
 3727         {
 3728             /* was a user, not a server and user isn't seen as a chanop here */
 3729 
 3730             if (MyConnect(sptr))
 3731             {
 3732                 /* user on _my_ server, with no chanops.. so go away */
 3733 
 3734                 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
 3735                            me.name, parv[0], chptr->chname);
 3736                 name = strtoken(&p, (char *) NULL, ",");
 3737                 continue;
 3738             }
 3739             
 3740             if (chptr->channelts == 0)
 3741             {
 3742                 /* If its a TS 0 channel, do it the old way */
 3743 
 3744                 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
 3745                            me.name, parv[0], chptr->chname);
 3746                 name = strtoken(&p, (char *) NULL, ",");
 3747                 continue;
 3748             }
 3749             /*
 3750              * Its a user doing a kick, but is not showing as chanop
 3751              * locally its also not a user ON -my- server, and the channel
 3752              * has a TS. There are two cases we can get to this point
 3753              * then...
 3754              * 
 3755              * 1) connect burst is happening, and for some reason a legit op
 3756              * has sent a KICK, but the SJOIN hasn't happened yet or been
 3757              * seen. (who knows.. due to lag...)
 3758              * 
 3759              * 2) The channel is desynced. That can STILL happen with TS
 3760              * 
 3761              * Now, the old code roger wrote, would allow the KICK to go
 3762              * through. Thats quite legit, but lets weird things like
 3763              * KICKS by users who appear not to be chanopped happen, or
 3764              * even neater, they appear not to be on the channel. This
 3765              * fits every definition of a desync, doesn't it? ;-) So I
 3766              * will allow the KICK, otherwise, things are MUCH worse. But
 3767              * I will warn it as a possible desync.
 3768              * 
 3769              * -Dianora
 3770              *
 3771              * sendto_one(sptr, err_str(ERR_DESYNC), me.name, parv[0],
 3772              * chptr->chname);
 3773              *
 3774              * After more discussion with orabidoo...
 3775              * 
 3776              * The code was sound, however, what happens if we have +h (TS4)
 3777              * and some servers don't understand it yet? we will be seeing
 3778              * servers with users who appear to have no chanops at all,
 3779              * merrily kicking users.... -Dianora
 3780              * 
 3781              */
 3782         }
 3783 
 3784         user = strtoken(&p2, parv[2], ",");
 3785         user_count = 4;
 3786         while (user && user_count)
 3787         {
 3788             user_count--;
 3789             if (!(who = find_chasing(sptr, user, &chasing)))
 3790             {
 3791                 user = strtoken(&p2, (char *) NULL, ",");
 3792                 continue;               /* No such user left! */
 3793             }
 3794 
 3795             if (IsMember(who, chptr))
 3796             {
 3797                 if(MyClient(sptr))
 3798                 {
 3799 #ifdef SPAMFILTER
 3800                     if(!(chptr->mode.mode & MODE_PRIVACY) && check_sf(sptr, comment, "kick", SF_CMD_KICK, chptr->chname))
 3801                         return FLUSH_BUFFER;
 3802 #endif
 3803 #ifdef USE_HALFOPS
 3804                     if(cankick != 2)
 3805                     {
 3806                         chanMember *cm = find_user_member(chptr->members, who);
 3807                         if(cm)
 3808                         {
 3809                             /* Don't allow half-ops to kick ops, other half-ops or voiced users */
 3810                             if(cm->flags & (CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE))
 3811                             {
 3812                                 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
 3813                                      me.name, parv[0], chptr->chname);
 3814                                 return 0;
 3815                             }
 3816                         }
 3817                     }
 3818 #endif
 3819                 }
 3820                 if((chptr->mode.mode & MODE_AUDITORIUM) && !is_chan_opvoice(who, chptr))
 3821                 {
 3822                     sendto_channelopvoice_butserv_me(chptr, sptr,
 3823                                                      ":%s KICK %s %s :%s", parv[0],
 3824                                                      name, who->name, comment);
 3825                     sendto_one(who, ":%s KICK %s %s :%s", parv[0], name, who->name, comment);
 3826                 }
 3827                 else
 3828                     sendto_channel_butserv(chptr, sptr,
 3829                                            ":%s KICK %s %s :%s", parv[0],
 3830                                            name, who->name, comment);
 3831                 sendto_serv_butone(cptr, ":%s KICK %s %s :%s", parv[0], name,
 3832                                    who->name, comment);
 3833                 remove_user_from_channel(who, chptr);
 3834             }
 3835             else
 3836                 sendto_one(sptr, err_str(ERR_USERNOTINCHANNEL),
 3837                            me.name, parv[0], user, name);
 3838             user = strtoken(&p2, (char *) NULL, ",");
 3839         }                               /* loop on parv[2] */
 3840 
 3841         name = strtoken(&p, (char *) NULL, ",");
 3842     }                           /* loop on parv[1] */
 3843 
 3844     return (0);
 3845 }
 3846 
 3847 int count_channels(aClient *sptr)
 3848 {
 3849     aChannel *chptr;
 3850     int     count = 0;
 3851 
 3852     for (chptr = channel; chptr; chptr = chptr->nextch)
 3853         count++;
 3854     return (count);
 3855 }
 3856 
 3857 void send_topic_burst(aClient *cptr)
 3858 {
 3859     aChannel *chptr;
 3860     aClient *acptr;
 3861     struct FlagList *xflag;
 3862     char *tmpptr;            /* Temporary pointer to remove the user@host part from tnick for non-NICKIPSTR servers */
 3863     char tnick[NICKLEN + 1]; /* chptr->topic_nick without the user@host part for non-NICKIPSTR servers */
 3864     int len;                 /* tnick's length */
 3865 
 3866     if (!(confopts & FLAGS_SERVHUB) || !(cptr->serv->uflags & ULF_NOBTOPIC))
 3867         for (chptr = channel; chptr; chptr = chptr->nextch)
 3868         {
 3869             if(chptr->topic[0] != '\0')
 3870             {
 3871                 if(cptr->capabilities & CAPAB_NICKIPSTR)
 3872                     sendto_one(cptr, ":%s TOPIC %s %s %ld :%s", me.name, chptr->chname,
 3873                                chptr->topic_nick, (long)chptr->topic_time,
 3874                    chptr->topic);
 3875                 else
 3876                 {
 3877                     /* This is a non-NICKIPSTR server, we need to remove the user@host part before we send it */
 3878                     tmpptr = chptr->topic_nick;
 3879                     len = 0;
 3880                     while(*tmpptr && *tmpptr!='!')
 3881                         tnick[len++] = *(tmpptr++);
 3882                     tnick[len] = '\0';
 3883                     sendto_one(cptr, ":%s TOPIC %s %s %ld :%s", me.name, chptr->chname,
 3884                                tnick, (long)chptr->topic_time,
 3885                    chptr->topic);
 3886                 }
 3887             }
 3888             if(chptr->xflags & XFLAG_SET)
 3889             {
 3890                 /* Not very optimized but we'll survive... -Kobi. */
 3891                 sendto_one(cptr, ":%s SVSXCF %s JOIN_CONNECT_TIME:%d MAX_MSG_TIME:%d:%d TALK_CONNECT_TIME:%d TALK_JOIN_TIME:%d", me.name, chptr->chname, chptr->join_connect_time, chptr->max_messages, chptr->max_messages_time, chptr->talk_connect_time, chptr->talk_join_time);
 3892                 for(xflag = xflags_list; xflag->option; xflag++)
 3893                 {
 3894                     if(!strcmp(xflag->option,"USER_VERBOSE") || !strcmp(xflag->option,"OPER_VERBOSE")) continue;
 3895                     sendto_one(cptr, ":%s SVSXCF %s %s:%d", me.name, chptr->chname, xflag->option, (chptr->xflags & xflag->flag)?1:0);
 3896                 }
 3897                 if(chptr->greetmsg && (chptr->max_bans != MAXBANS))
 3898                     sendto_one(cptr, ":%s SVSXCF %s MAX_BANS:%d GREETMSG :%s", me.name, chptr->chname, chptr->max_bans, chptr->greetmsg);
 3899                 else if(chptr->greetmsg)
 3900                     sendto_one(cptr, ":%s SVSXCF %s GREETMSG :%s", me.name, chptr->chname, chptr->greetmsg);
 3901                 else if(chptr->max_bans != MAXBANS)
 3902                     sendto_one(cptr, ":%s SVSXCF %s MAX_BANS:%d", me.name, chptr->chname, chptr->max_bans);
 3903                 if(chptr->max_invites != MAXINVITELIST)
 3904                     sendto_one(cptr, ":%s SVSXCF %s MAX_INVITES:%d", me.name, chptr->chname, chptr->max_invites);
 3905             }
 3906         }
 3907 
 3908     if (!(confopts & FLAGS_SERVHUB) || !(cptr->serv->uflags & ULF_NOBAWAY))
 3909         for (acptr = client; acptr; acptr = acptr->next)
 3910         {
 3911             if(!IsPerson(acptr) || acptr->from == cptr)
 3912                 continue;
 3913             if(acptr->user->away)
 3914                 sendto_one(cptr, ":%s AWAY :%s", acptr->name, acptr->user->away);
 3915         }
 3916 }
 3917 
 3918 /*
 3919  * m_topic 
 3920  * parv[0] = sender prefix 
 3921  * parv[1] = topic text
 3922  */
 3923 int m_topic(aClient *cptr, aClient *sptr, int parc, char *parv[])
 3924 {
 3925     aChannel   *chptr = NullChn;
 3926     char       *topic = NULL, *name, *tnick;
 3927     char       *tmpptr; /* Temporary pointer to remove the user@host part from tnick for non-NICKIPSTR servers */
 3928     time_t     ts = timeofday;
 3929     int        member;  
 3930 
 3931     if (parc < 2) 
 3932     {
 3933         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
 3934                    "TOPIC");
 3935         return 0;
 3936     }
 3937         
 3938     name = parv[1];
 3939     chptr = find_channel(name, NullChn);
 3940     if(!chptr) 
 3941     {
 3942         sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], name);
 3943         return 0;
 3944     }
 3945     
 3946     member = IsMember(sptr, chptr);
 3947     
 3948     if (parc == 2) /* user is requesting a topic */ 
 3949     {   
 3950         char *namep = chptr->chname;
 3951         char tempchname[CHANNELLEN + 2];
 3952 
 3953         if(!member && !(ShowChannel(sptr, chptr)))
 3954         {
 3955             if(IsAdmin(sptr))
 3956             {
 3957                 tempchname[0] = '%';
 3958                 strcpy(&tempchname[1], chptr->chname);
 3959                 namep = tempchname;
 3960             }
 3961             else
 3962             {
 3963                 sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
 3964                            name);
 3965                 return 0;
 3966             }
 3967         }
 3968 
 3969         if (chptr->topic[0] == '\0')
 3970             sendto_one(sptr, rpl_str(RPL_NOTOPIC), me.name, parv[0], namep);
 3971         else 
 3972         {
 3973             sendto_one(sptr, rpl_str(RPL_TOPIC), me.name, parv[0], namep,
 3974                        chptr->topic);
 3975             sendto_one(sptr, rpl_str(RPL_TOPICWHOTIME), me.name, parv[0],
 3976                        namep, chptr->topic_nick, chptr->topic_time);
 3977         }
 3978         return 0;
 3979     }
 3980 
 3981     topic = parv[2];
 3982 
 3983     if (MyClient(sptr))
 3984     {
 3985         if (!member)
 3986         {
 3987             sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],name);
 3988             return 0;
 3989         }
 3990 
 3991 #ifdef USE_HALFOPS
 3992         if ((chptr->mode.mode & MODE_TOPICLIMIT) && !is_chan_cankick(sptr, chptr))
 3993 #else
 3994         if ((chptr->mode.mode & MODE_TOPICLIMIT) && !is_chan_op(sptr, chptr))
 3995 #endif
 3996         {
 3997             sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
 3998                        chptr->chname);
 3999             return 0;
 4000         }
 4001 #ifdef SPAMFILTER
 4002         if(!(chptr->mode.mode & MODE_PRIVACY) && check_sf(sptr, topic, "topic", SF_CMD_TOPIC, chptr->chname))
 4003             return FLUSH_BUFFER;
 4004 #endif
 4005 
 4006         /* if -t and banned, you can't change the topic */
 4007         if (!(chptr->mode.mode & MODE_TOPICLIMIT) && !is_chan_op(sptr, chptr) && is_banned(sptr, chptr, NULL))
 4008         {
 4009             sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0], chptr->chname);
 4010             return 0;
 4011         }
 4012 
 4013         tnick = make_nick_user_host(sptr->name, sptr->user->username, GET_USER_HOST(sptr));
 4014     }
 4015     else
 4016     {
 4017         /* extended info */
 4018         if (parc > 3)
 4019         {
 4020             topic = (parc > 4 ? parv[4] : "");
 4021             tnick = parv[2];
 4022             ts = atoi(parv[3]);
 4023         }
 4024         else tnick = sptr->name;
 4025 
 4026         /* ignore old topics during burst/race */
 4027         if (!IsULine(sptr) && chptr->topic[0] && chptr->topic_time >= ts)
 4028             return 0;
 4029     }
 4030 
 4031     if(chptr->topic_time==ts && !mycmp(chptr->topic, topic) && !mycmp(chptr->topic_nick, tnick))
 4032         return 0; /* Don't spam the network if it's the same topic -Kobi_S */
 4033 
 4034     strncpyzt(chptr->topic, topic, TOPICLEN + 1);
 4035     strcpy(chptr->topic_nick, tnick);
 4036     chptr->topic_time = ts;
 4037 
 4038     /* in this case I think it's better that we send all the info that df
 4039      * sends with the topic, so I changed everything to work like that.
 4040      * -wd */
 4041 
 4042     sendto_capab_serv_butone(cptr, CAPAB_NICKIPSTR, 0, ":%s TOPIC %s %s %lu :%s", parv[0],
 4043                              chptr->chname, chptr->topic_nick,
 4044                              (unsigned long)chptr->topic_time, chptr->topic);
 4045     if((tmpptr = strchr(tnick, '!')))
 4046         *tmpptr = '\0'; /* Remove the user@host part before we send it to non-NICKIPSTR servers */
 4047     sendto_capab_serv_butone(cptr, 0, CAPAB_NICKIPSTR, ":%s TOPIC %s %s %lu :%s", parv[0],
 4048                              chptr->chname, tnick,
 4049                              (unsigned long)chptr->topic_time, chptr->topic);
 4050     sendto_channel_butserv_me(chptr, sptr, ":%s TOPIC %s :%s", parv[0],
 4051                               chptr->chname, chptr->topic);
 4052         
 4053     return 0;
 4054 }
 4055 
 4056 /*
 4057  * m_invite 
 4058  * parv[0] - sender prefix 
 4059  * parv[1] - user to invite 
 4060  * parv[2] - channel name
 4061  */
 4062 int m_invite(aClient *cptr, aClient *sptr, int parc, char *parv[])
 4063 {
 4064     aClient    *acptr;
 4065     aChannel   *chptr = NULL;
 4066     
 4067     if (parc < 3 || *parv[1] == 0)
 4068     {
 4069         sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
 4070                    "INVITE");
 4071         return -1;
 4072     }
 4073 
 4074     if (!(acptr = find_person(parv[1], NULL)))
 4075     {
 4076         sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
 4077         return 0;
 4078     }
 4079 
 4080     if (MyClient(sptr))
 4081     {
 4082         if (!(chptr = find_channel(parv[2], NULL)))
 4083         {
 4084             sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0],
 4085                        parv[2]);
 4086             return 0;
 4087         }
 4088 
 4089         if (!IsMember(sptr, chptr))
 4090         {
 4091             sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0],
 4092                        parv[2]);
 4093             return 0;
 4094         }
 4095 
 4096         if (IsMember(acptr, chptr))
 4097         {
 4098             sendto_one(sptr, err_str(ERR_USERONCHANNEL), me.name, parv[0],
 4099                        parv[1], chptr->chname);
 4100             return 0;
 4101         }
 4102 
 4103         if (!is_chan_op(sptr, chptr))
 4104         {
 4105             sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0],
 4106                        chptr->chname);
 4107             return 0;
 4108         }
 4109 
 4110         if (!IsULine(sptr) && !IsOper(sptr))
 4111         {
 4112             if (IsNoNonReg(acptr) && !IsRegNick(sptr))
 4113             {
 4114                 sendto_one(sptr, err_str(ERR_NONONREG), me.name, parv[0], acptr->name);
 4115                 return 0;
 4116             }
 4117 
 4118             if (IsUmodeC(acptr) && (!IsNoNonReg(acptr) || IsRegNick(sptr)) && acptr->user->joined && !find_shared_chan(sptr, acptr))
 4119             {
 4120                 sendto_one(sptr, err_str(ERR_NOSHAREDCHAN), me.name, parv[0], acptr->name);
 4121                 return 0;
 4122             }
 4123         }
 4124 
 4125         sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0], acptr->name,
 4126                    chptr->chname);
 4127 
 4128         if (acptr->user->away)
 4129             sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], acptr->name,
 4130                        acptr->user->away);
 4131     }
 4132 
 4133     if (MyClient(acptr))
 4134     {
 4135         /* stuff already done above */
 4136         if (!MyClient(sptr))
 4137         {
 4138             if (!(chptr = find_channel(parv[2], NullChn)))
 4139                 return 0;
 4140 
 4141             if (IsMember(acptr, chptr))
 4142                 return 0;
 4143         }
 4144 
 4145         add_invite(acptr, chptr);
 4146 
 4147         if (!is_silenced(sptr, acptr))
 4148             sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
 4149                               acptr->name, chptr->chname);
 4150         sendto_channelflags_butone(NULL, &me, chptr, CHFL_CHANOP,
 4151                                    ":%s NOTICE @%s :%s invited %s into "
 4152                                    "channel %s", me.name, chptr->chname,
 4153                                    parv[0], acptr->name, chptr->chname);
 4154 
 4155         return 0;
 4156     }
 4157 
 4158     sendto_one(acptr, ":%s INVITE %s :%s", parv[0], parv[1], parv[2]);
 4159 
 4160     return 0;
 4161 }
 4162 
 4163 
 4164 /*
 4165  * The function which sends the actual channel list back to the user.
 4166  * Operates by stepping through the hashtable, sending the entries back if
 4167  * they match the criteria.
 4168  * cptr = Local client to send the output back to.
 4169  * numsend = Number (roughly) of lines to send back. Once this number has
 4170  * been exceeded, send_list will finish with the current hash bucket,
 4171  * and record that number as the number to start next time send_list
 4172  * is called for this user. So, this function will almost always send
 4173  * back more lines than specified by numsend (though not by much,
 4174  * assuming CH_MAX is was well picked). So be conservative in your choice
 4175  * of numsend. -Rak
 4176  */
 4177 
 4178 void send_list(aClient *cptr, int numsend)
 4179 {
 4180     aChannel    *chptr;
 4181     LOpts       *lopt = cptr->user->lopt;
 4182     int         hashnum;
 4183     
 4184     for (hashnum = lopt->starthash; hashnum < CH_MAX; hashnum++)
 4185     {
 4186         if (numsend > 0)
 4187         {
 4188             for (chptr = (aChannel *)hash_get_chan_bucket(hashnum); 
 4189                  chptr; chptr = chptr->hnextch)
 4190             {
 4191                 if (!PubChannel(chptr) && !IsAdmin(cptr)
 4192                     && !IsMember(cptr, chptr))
 4193                     continue;
 4194 #ifdef USE_CHANMODE_L
 4195                 if (lopt->only_listed && !(chptr->mode.mode & MODE_LISTED))
 4196                     continue;
 4197 #endif
 4198                 if ((!lopt->showall) && ((chptr->users < lopt->usermin) ||
 4199                                          ((lopt->usermax >= 0) && 
 4200                                           (chptr->users > lopt->usermax)) ||
 4201                                          ((chptr->channelts) < 
 4202                                           lopt->chantimemin) ||
 4203                                          (chptr->topic_time < 
 4204                                           lopt->topictimemin) ||
 4205                                          (chptr->channelts > 
 4206                                           lopt->chantimemax) ||
 4207                                          (chptr->topic_time > 
 4208                                           lopt->topictimemax) ||
 4209                                          (lopt->nolist && 
 4210                                           find_str_link(lopt->nolist, 
 4211                                                         chptr->chname)) ||
 4212                                          (lopt->yeslist && 
 4213                                           !find_str_link(lopt->yeslist, 
 4214                                                          chptr->chname))))
 4215                     continue;
 4216 
 4217                 /* Seem'd more efficent to seperate into two commands 
 4218                  * then adding an or to the inline. -- Doc.
 4219                  */
 4220                 if (IsAdmin(cptr))
 4221                 {
 4222                     char tempchname[CHANNELLEN + 2], *altchname;
 4223 
 4224                     if (!PubChannel(chptr) && !IsMember(cptr, chptr))
 4225                     {
 4226                         tempchname[0] = '%';
 4227                         strcpy(&tempchname[1], chptr->chname);
 4228                         altchname = &tempchname[0];
 4229                     } 
 4230                     else 
 4231                         altchname = chptr->chname;
 4232 
 4233                     sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name,
 4234                                altchname, chptr->users, chptr->topic);
 4235                 } 
 4236                 else 
 4237                 {
 4238                     sendto_one(cptr, rpl_str(RPL_LIST), me.name, cptr->name,
 4239                                chptr->chname,
 4240                                chptr->users,
 4241                                chptr->topic);
 4242                 }
 4243                 numsend--;
 4244             }
 4245         }
 4246         else
 4247             break;
 4248     }
 4249     
 4250     /* All done */
 4251     if (hashnum == CH_MAX)
 4252     {
 4253         Link *lp, *next;
 4254         sendto_one(cptr, rpl_str(RPL_LISTEND), me.name, cptr->name);
 4255         for (lp = lopt->yeslist; lp; lp = next)
 4256         {
 4257             next = lp->next;
 4258             MyFree(lp->value.cp);
 4259             free_link(lp);
 4260         }
 4261         for (lp = lopt->nolist; lp; lp = next)
 4262         {
 4263             next = lp->next;
 4264             MyFree(lp->value.cp);
 4265             free_link(lp);
 4266         }
 4267         
 4268         MyFree(cptr->user->lopt);
 4269         cptr->user->lopt = NULL;
 4270         remove_from_list(&listing_clients, cptr, NULL);
 4271         return;
 4272     }
 4273     
 4274     /* 
 4275      * We've exceeded the limit on the number of channels to send back
 4276      * at once.
 4277      */
 4278     lopt->starthash = hashnum;
 4279     return;
 4280 }
 4281 
 4282 
 4283 /*
 4284  * m_list 
 4285  * parv[0] = sender prefix
 4286  * parv[1] = channel
 4287  */
 4288 int m_list(aClient *cptr, aClient *sptr, int parc, char *parv[])
 4289 {
 4290     aChannel    *chptr;
 4291     time_t      currenttime = time(NULL);
 4292     char        *name, *p = NULL;
 4293     LOpts       *lopt = NULL;
 4294     Link        *lp, *next;
 4295     int         usermax, usermin, error = 0, doall = 0, only_listed = 1;
 4296     int         x;
 4297     time_t      chantimemin, chantimemax;
 4298     ts_val      topictimemin, topictimemax;
 4299     Link        *yeslist = NULL, *nolist = NULL;
 4300     
 4301     static char *usage[] = {
 4302         "   Usage: /raw LIST options (on mirc) or /quote LIST options (ircII)",
 4303         "",
 4304         "If you don't include any options, the default is to send you the",
 4305         "entire unfiltered list of channels. Below are the options you can",
 4306         "use, and what channels LIST will return when you use them.",
 4307         ">number  List channels with more than <number> people.",
 4308         "<number  List channels with less than <number> people.",
 4309         "C>number List channels created between now and <number> minutes ago.",
 4310         "C<number List channels created earlier than <number> minutes ago.",
 4311         "T>number List channels whose topics are older than <number> minutes",
 4312         "         (Ie, they have not changed in the last <number> minutes.",
 4313         "T<number List channels whose topics are not older than <number> "
 4314         "minutes.",
 4315         "*mask*   List channels that match *mask*",
 4316         "!*mask*  List channels that do not match *mask*",
 4317         NULL
 4318     };
 4319 
 4320     /* Some starting san checks -- No interserver lists allowed. */
 4321     if (cptr != sptr || !sptr->user) return 0;
 4322 
 4323     if (IsSquelch(sptr)) 
 4324     {
 4325         sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
 4326         return 0;
 4327     }
 4328 
 4329     /* If a /list is in progress, then another one will cancel it */
 4330     if ((lopt = sptr->user->lopt)!=NULL)
 4331     {
 4332         sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
 4333         for (lp = lopt->yeslist; lp; lp = next)
 4334         {
 4335             next = lp->next;
 4336             MyFree(lp->value.cp);
 4337             free_link(lp);
 4338         }
 4339         for (lp = lopt->nolist; lp; lp = next)
 4340         {
 4341             next = lp->next;
 4342             MyFree(lp->value.cp);
 4343             free_link(lp);
 4344         }
 4345         MyFree(sptr->user->lopt);
 4346         sptr->user->lopt = NULL;
 4347         remove_from_list(&listing_clients, sptr, NULL);
 4348         return 0;
 4349     }
 4350 
 4351     if (parc < 2 || BadPtr(parv[1]))
 4352     {
 4353 
 4354         sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, parv[0]);
 4355         lopt = sptr->user->lopt = (LOpts *) MyMalloc(sizeof(LOpts));
 4356         memset(lopt, '\0', sizeof(LOpts));
 4357 
 4358         lopt->showall = 1;
 4359 #ifdef USE_CHANMODE_L
 4360         lopt->only_listed = 1;
 4361 #endif
 4362 
 4363         add_to_list(&listing_clients, sptr);
 4364 
 4365         if (SBufLength(&cptr->sendQ) < 2048)
 4366             send_list(cptr, 64);
 4367 
 4368         return 0;
 4369     }
 4370 
 4371     if ((parc == 2) && (parv[1][0] == '?') && (parv[1][1] == '\0'))
 4372     {
 4373         char **ptr = usage;
 4374         for (; *ptr; ptr++)
 4375             sendto_one(sptr, rpl_str(RPL_COMMANDSYNTAX), me.name,
 4376                        cptr->name, *ptr);
 4377         return 0;
 4378     }
 4379 
 4380     sendto_one(sptr, rpl_str(RPL_LISTSTART), me.name, parv[0]);
 4381 
 4382     chantimemax = topictimemax = currenttime + 86400;
 4383     chantimemin = topictimemin = 0;
 4384     usermin = 0;
 4385     usermax = -1; /* No maximum */
 4386 
 4387     for (name = strtoken(&p, parv[1], ","); name && !error;
 4388          name = strtoken(&p, (char *) NULL, ","))
 4389     {
 4390 
 4391         switch (*name)
 4392         {
 4393             case '<':
 4394                 usermax = atoi(name+1) - 1;
 4395                 doall = 1;
 4396                 break;
 4397             case '>':
 4398                 usermin = atoi(name+1) + 1;
 4399                 doall = 1;
 4400                 break;
 4401 #ifdef USE_CHANMODE_L
 4402             case '-':
 4403                 if(!strcasecmp(++name,"all")) 
 4404                 {
 4405                     only_listed = 0;
 4406                     doall = 1;
 4407                 }
 4408                 break;                          
 4409 #endif
 4410             case 'C':
 4411             case 'c': /* Channel TS time -- creation time? */
 4412                 ++name;
 4413                 switch (*name++)
 4414                 {
 4415                     case '<':
 4416                         chantimemax = currenttime - 60 * atoi(name);
 4417                         doall = 1;
 4418                         break;
 4419                     case '>':
 4420                         chantimemin = currenttime - 60 * atoi(name);
 4421                         doall = 1;
 4422                         break;
 4423                     default:
 4424                         sendto_one(sptr, err_str(ERR_LISTSYNTAX), me.name, 
 4425                                 cptr->name);
 4426                         error = 1;
 4427                 }
 4428                 break;
 4429             case 'T':
 4430             case 't':
 4431                 ++name;
 4432                 switch (*name++)
 4433                 {
 4434                     case '<':
 4435                         topictimemax = currenttime - 60 * atoi(name);
 4436                         doall = 1;
 4437                         break;
 4438                     case '>':
 4439                         topictimemin = currenttime - 60 * atoi(name);
 4440                         doall = 1;
 4441                         break;
 4442                     default:
 4443                         sendto_one(sptr, err_str(ERR_LISTSYNTAX), me.name, 
 4444                                 cptr->name);
 4445                         error = 1;
 4446                 }
 4447                 break;
 4448             default: /* A channel, possibly with wildcards.
 4449                       * Thought for the future: Consider turning wildcard
 4450                       * processing on the fly.
 4451                       * new syntax: !channelmask will tell ircd to ignore
 4452                       * any channels matching that mask, and then
 4453                       * channelmask will tell ircd to send us a list of
 4454                       * channels only masking channelmask. Note: Specifying
 4455                       * a channel without wildcards will return that
 4456                       * channel even if any of the !channelmask masks
 4457                       * matches it.
 4458                       */
 4459                 if (*name == '!')
 4460                 {
 4461                     doall = 1;
 4462                     lp = make_link();
 4463                     lp->next = nolist;
 4464                     nolist = lp;
 4465                     DupString(lp->value.cp, name+1);
 4466                 }
 4467                 else if (strchr(name, '*') || strchr(name, '?'))
 4468                 {
 4469                     doall = 1;
 4470                     lp = make_link();
 4471                     lp->next = yeslist;
 4472                     yeslist = lp;
 4473                     DupString(lp->value.cp, name);
 4474                 }
 4475                 else /* Just a normal channel */
 4476                 {
 4477                     chptr = find_channel(name, NullChn);
 4478                     if (chptr && ((x = ShowChannel(sptr, chptr)) || 
 4479                                     IsAdmin(sptr)))
 4480                     {
 4481                         char *nameptr = name;
 4482                         char channame[CHANNELLEN + 2];
 4483 
 4484                         if(!x && IsAdmin(sptr))
 4485                         {
 4486                             channame[0] = '%';
 4487                             strcpy(&channame[1], chptr->chname);
 4488                             nameptr = channame;
 4489                         }
 4490 
 4491                         sendto_one(sptr, rpl_str(RPL_LIST), me.name, parv[0],
 4492                                nameptr, chptr->users, chptr->topic);
 4493                     }
 4494                 }
 4495         } /* switch */
 4496     } /* while */
 4497 
 4498     if (doall)
 4499     {
 4500         lopt = sptr->user->lopt = (LOpts *) MyMalloc(sizeof(LOpts));
 4501         memset(lopt, '\0', sizeof(LOpts));
 4502         lopt->usermin = usermin;
 4503         lopt->usermax = usermax;
 4504         lopt->topictimemax = topictimemax;
 4505         lopt->topictimemin = topictimemin;
 4506         lopt->chantimemax = chantimemax;
 4507         lopt->chantimemin = chantimemin;
 4508         lopt->nolist = nolist;
 4509         lopt->yeslist = yeslist;
 4510         lopt->only_listed = only_listed;
 4511 
 4512         add_to_list(&listing_clients, sptr);
 4513 
 4514         if (SBufLength(&cptr->sendQ) < 2048)
 4515             send_list(cptr, 64);
 4516         return 0;
 4517     }
 4518 
 4519     sendto_one(sptr, rpl_str(RPL_LISTEND), me.name, parv[0]);
 4520 
 4521     return 0;
 4522 }
 4523 
 4524 
 4525 
 4526 /************************************************************************
 4527  * m_names() - Added by Jto 27 Apr 1989
 4528  * 12 Feb 2000 - geesh, time for a rewrite -lucas
 4529  ************************************************************************/
 4530 /*
 4531  * m_names 
 4532  * parv[0] = sender prefix 
 4533  * parv[1] = channel
 4534  */
 4535 
 4536 /* maximum names para to show to opers when abuse occurs */
 4537 #define TRUNCATED_NAMES 64
 4538 
 4539 int m_names(aClient *cptr, aClient *sptr, int parc, char *parv[])
 4540 {
 4541     int mlen = strlen(me.name) + NICKLEN + 7;
 4542     aChannel *chptr;
 4543     aClient *acptr;
 4544     int member;
 4545     chanMember *cm;
 4546     int idx, flag = 1, spos;
 4547     char *s, *para = parv[1];
 4548 
 4549     if (parc < 2 || !MyConnect(sptr)) 
 4550     {
 4551         sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], "*");
 4552         return 0;
 4553     }
 4554 
 4555     for(s = para; *s; s++) 
 4556     {
 4557         if(*s == ',') 
 4558         {
 4559             if(strlen(para) > TRUNCATED_NAMES)
 4560                 para[TRUNCATED_NAMES] = '\0';
 4561             sendto_realops("names abuser %s %s", get_client_name(sptr, FALSE),
 4562                            para);
 4563             sendto_one(sptr, err_str(ERR_TOOMANYTARGETS), me.name, sptr->name,
 4564                        "NAMES");
 4565             return 0;
 4566         }
 4567     }
 4568 
 4569     if(!check_channelname(sptr, (unsigned char *)para))
 4570         return 0;
 4571      
 4572     chptr = find_channel(para, (aChannel *) NULL);
 4573 
 4574     if (!chptr || !ShowChannel(sptr, chptr))
 4575     {
 4576         sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], para);
 4577         return 0;
 4578     }
 4579 
 4580     /* cache whether this user is a member of this channel or not */
 4581     member = IsMember(sptr, chptr);
 4582     
 4583     if(PubChannel(chptr))
 4584         buf[0] = '=';
 4585     else if(SecretChannel(chptr))
 4586         buf[0] = '@';
 4587     else
 4588         buf[0] = '*';
 4589 
 4590     idx = 1;
 4591     buf[idx++] = ' ';
 4592     for(s = chptr->chname; *s; s++)
 4593         buf[idx++] = *s;
 4594     buf[idx++] = ' ';
 4595     buf[idx++] = ':';
 4596 
 4597     /* If we go through the following loop and never add anything,
 4598        we need this to be empty, otherwise spurious things from the
 4599        LAST /names call get stuck in there.. - lucas */
 4600     buf[idx] = '\0';
 4601 
 4602     spos = idx; /* starting point in buffer for names!*/
 4603 
 4604     for (cm = chptr->members; cm; cm = cm->next) 
 4605     {
 4606         acptr = cm->cptr;
 4607         if(IsInvisible(acptr) && !member)
 4608             continue;
 4609         if(cm->flags & CHFL_CHANOP)
 4610             buf[idx++] = '@';
 4611 #ifdef USE_HALFOPS
 4612         else if(cm->flags & CHFL_HALFOP)
 4613             buf[idx++] = '%';
 4614 #endif
 4615         else if(cm->flags & CHFL_VOICE)
 4616             buf[idx++] = '+';
 4617         else if((chptr->mode.mode & MODE_AUDITORIUM) && (sptr != acptr) && !is_chan_opvoice(sptr, chptr) && !IsAnOper(sptr)) continue;
 4618         for(s = acptr->name; *s; s++)
 4619             buf[idx++] = *s;
 4620         buf[idx++] = ' ';
 4621         buf[idx] = '\0';
 4622         flag = 1;
 4623         if(mlen + idx + NICKLEN > BUFSIZE - 3)
 4624         {
 4625             sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
 4626             idx = spos;
 4627             flag = 0;
 4628         }
 4629     }
 4630 
 4631     if (flag) 
 4632         sendto_one(sptr, rpl_str(RPL_NAMREPLY), me.name, parv[0], buf);
 4633     
 4634     sendto_one(sptr, rpl_str(RPL_ENDOFNAMES), me.name, parv[0], para);
 4635     
 4636     return 0;
 4637 }
 4638  
 4639 void send_user_joins(aClient *cptr, aClient *user)
 4640 {
 4641     Link   *lp;
 4642     aChannel *chptr;
 4643     int     cnt = 0, len = 0;
 4644     size_t  clen;
 4645     char       *mask;
 4646 
 4647     *buf = ':';
 4648     (void) strcpy(buf + 1, user->name);
 4649     (void) strcat(buf, " JOIN ");
 4650     len = strlen(user->name) + 7;
 4651 
 4652     for (lp = user->user->channel; lp; lp = lp->next)
 4653     {
 4654         chptr = lp->value.chptr;
 4655         if (*chptr->chname == '&')
 4656             continue;
 4657         if ((mask = strchr(chptr->chname, ':')))
 4658             if (match(++mask, cptr->name))
 4659                 continue;
 4660         clen = strlen(chptr->chname);
 4661         if (clen > (size_t) BUFSIZE - 7 - len)
 4662         {
 4663             if (cnt)
 4664                 sendto_one(cptr, "%s", buf);
 4665             *buf = ':';
 4666             (void) strcpy(buf + 1, user->name);
 4667             (void) strcat(buf, " JOIN ");
 4668             len = strlen(user->name) + 7;
 4669             cnt = 0;
 4670         }
 4671         (void) strcpy(buf + len, chptr->chname);
 4672         cnt++;
 4673         len += clen;
 4674         if (lp->next)
 4675         {
 4676             len++;
 4677             (void) strcat(buf, ",");
 4678         }
 4679     }
 4680     if (*buf && cnt)
 4681         sendto_one(cptr, "%s", buf);
 4682 
 4683     return;
 4684 }
 4685 
 4686 void kill_ban_list(aClient *cptr, aChannel *chptr)
 4687 {  
 4688     void        *pnx;
 4689     aBan        *bp;
 4690 #ifdef EXEMPT_LISTS
 4691     aBanExempt  *ep;
 4692 #endif
 4693 #ifdef INVITE_LISTS
 4694     anInvite   *ip;
 4695 #endif
 4696     char       *cp;
 4697     int         count = 0, send = 0;
 4698 
 4699     cp = modebuf;  
 4700     *cp++ = '-';
 4701     *cp = '\0';      
 4702 
 4703     *parabuf = '\0';
 4704 
 4705     for (bp = chptr->banlist; bp; bp = bp->next)
 4706     {  
 4707         if (strlen(parabuf) + strlen(bp->banstr) + 10 < (size_t) MODEBUFLEN)
 4708         {  
 4709             if(*parabuf)
 4710                 strcat(parabuf, " ");
 4711             strcat(parabuf, bp->banstr);
 4712             count++;   
 4713             *cp++ = 'b';
 4714             *cp = '\0';
 4715         }
 4716         else if (*parabuf)
 4717             send = 1;
 4718    
 4719         if (count == MAXMODEPARAMS)
 4720             send = 1;
 4721     
 4722         if (send) {
 4723             sendto_channel_butserv_me(chptr, cptr, ":%s MODE %s %s %s",
 4724                          cptr->name, chptr->chname, modebuf, parabuf);
 4725             send = 0;
 4726             *parabuf = '\0';
 4727             cp = modebuf;
 4728             *cp++ = '-';
 4729             if (count != MAXMODEPARAMS)
 4730             {
 4731                 strcpy(parabuf, bp->banstr);
 4732                 *cp++ = 'b';
 4733                 count = 1;
 4734             }
 4735             else
 4736                 count = 0; 
 4737             *cp = '\0';
 4738         }
 4739     }
 4740 
 4741 #ifdef EXEMPT_LISTS
 4742     for (ep = chptr->banexempt_list; ep; ep = ep->next)
 4743     {
 4744         if (strlen(parabuf) + strlen(ep->banstr) + 10 < (size_t) MODEBUFLEN)
 4745         {
 4746             if(*parabuf)
 4747                 strcat(parabuf, " ");
 4748             strcat(parabuf, ep->banstr);
 4749             count++;
 4750             *cp++ = 'e';
 4751             *cp = '\0';
 4752         }
 4753         else if (*parabuf)
 4754             send = 1;
 4755 
 4756         if (count == MAXMODEPARAMS)
 4757             send = 1;
 4758 
 4759         if (send) {
 4760             sendto_channel_butserv_me(chptr, cptr, ":%s MODE %s %s %s",
 4761                                       cptr->name, chptr->chname, modebuf, parabuf);
 4762             send = 0;
 4763             *parabuf = '\0';
 4764             cp = modebuf;
 4765             *cp++ = '-';
 4766             if (count != MAXMODEPARAMS)
 4767             {
 4768                 strcpy(parabuf, ep->banstr);
 4769                 *cp++ = 'e';
 4770                 count = 1;
 4771             }
 4772             else
 4773                 count = 0;
 4774             *cp = '\0';
 4775         }
 4776     }
 4777 #endif
 4778 
 4779 #ifdef INVITE_LISTS
 4780     for (ip = chptr->invite_list; ip; ip = ip->next)
 4781     {
 4782         if (strlen(parabuf) + strlen(ip->invstr) + 10 < (size_t) MODEBUFLEN)
 4783         {
 4784             if(*parabuf)
 4785                 strcat(parabuf, " ");
 4786             strcat(parabuf, ip->invstr);
 4787             count++;
 4788             *cp++ = 'I';
 4789             *cp = '\0';
 4790         }
 4791         else if (*parabuf)
 4792             send = 1;
 4793 
 4794         if (count == MAXMODEPARAMS)
 4795             send = 1;
 4796 
 4797         if (send) {
 4798             sendto_channel_butserv_me(chptr, cptr, ":%s MODE %s %s %s",
 4799                                       cptr->name, chptr->chname, modebuf, parabuf);
 4800             send = 0;
 4801             *parabuf = '\0';
 4802             cp = modebuf;
 4803             *cp++ = '-';
 4804             if (count != MAXMODEPARAMS)
 4805             {
 4806                 strcpy(parabuf, ip->invstr);
 4807                 *cp++ = 'I';
 4808                 count = 1;
 4809             }
 4810             else
 4811                 count = 0;
 4812             *cp = '\0';
 4813         }
 4814     }
 4815 #endif
 4816 
 4817     if(*parabuf)
 4818     {
 4819         sendto_channel_butserv_me(chptr, cptr, ":%s MODE %s %s %s", cptr->name,
 4820                                   chptr->chname, modebuf, parabuf);
 4821     }
 4822 
 4823     /* physically destroy channel ban list */   
 4824 
 4825     bp = chptr->banlist;
 4826     while(bp)
 4827     {
 4828         pnx = bp->next;
 4829         MyFree(bp->banstr);
 4830         MyFree(bp->who);
 4831         MyFree(bp);
 4832         bp = pnx;
 4833     }
 4834     chptr->banlist = NULL;
 4835 
 4836 #ifdef EXEMPT_LISTS
 4837     ep = chptr->banexempt_list;
 4838     while(ep)
 4839     {
 4840         pnx = ep->next;
 4841         MyFree(ep->banstr);
 4842         MyFree(ep->who);
 4843         MyFree(ep);
 4844         ep = pnx;
 4845     }
 4846     chptr->banexempt_list = NULL;
 4847 #endif
 4848 
 4849 #ifdef INVITE_LISTS
 4850     ip = chptr->invite_list;
 4851     while(ip)
 4852     {
 4853         pnx = ip->next;
 4854         MyFree(ip->invstr);
 4855         MyFree(ip->who);
 4856         MyFree(ip);
 4857         ip = pnx;
 4858     }
 4859     chptr->invite_list = NULL;
 4860 #endif
 4861 
 4862     /* reset bquiet cache */
 4863     chptr->banserial++;
 4864 }
 4865 
 4866 static inline void sjoin_sendit(aClient *cptr, aClient *sptr,
 4867                                 aChannel *chptr, char *from)
 4868 {
 4869     sendto_channel_butserv_me(chptr, sptr, ":%s MODE %s %s %s", from,
 4870                               chptr->chname, modebuf, parabuf);
 4871 }
 4872 
 4873 /* m_resynch
 4874  *
 4875  * parv[0] = sender
 4876  * parv[1] = #channel
 4877  *
 4878  * Sent from a server I am directly connected to that is requesting I resend
 4879  * EVERYTHING I know about #channel.
 4880  */
 4881 int m_resynch(aClient *cptr, aClient *sptr, int parc, char *parv[])
 4882 {
 4883     aChannel *chptr;
 4884 
 4885     if(!MyConnect(sptr) || !IsServer(sptr) || parc < 2)
 4886         return 0;
 4887 
 4888     chptr = find_channel(parv[1], NullChn);
 4889 
 4890     sendto_realops_lev(DEBUG_LEV, "%s is requesting a resynch of %s%s", 
 4891                        parv[0], parv[1], (chptr == NullChn) ? " [failed]" : "");
 4892 
 4893     if (chptr != NullChn)
 4894         send_channel_modes(sptr, chptr);
 4895     return 0;
 4896 }
 4897 
 4898 /*
 4899  * m_sjoin 
 4900  * parv[0] - sender 
 4901  * parv[1] - TS 
 4902  * parv[2] - channel 
 4903  * parv[3] - modes + n arguments (key and/or limit) 
 4904  * parv[4+n] - flags+nick list (all in one parameter)
 4905  * 
 4906  * process a SJOIN, taking the TS's into account to either ignore the
 4907  * incoming modes or undo the existing ones or merge them, and JOIN all
 4908  * the specified users while sending JOIN/MODEs to non-TS servers and
 4909  * to clients
 4910  */
 4911 
 4912 #define INSERTSIGN(x,y) \
 4913 if (what != x) { \
 4914 *mbuf++=y; \
 4915 what = x; \
 4916 }
 4917 
 4918 #define SJ_MODEPLUS(x, y) \
 4919    if(((y) & mode.mode) && !((y) & oldmode->mode)) \
 4920    { \
 4921       INSERTSIGN(1, '+') \
 4922       *mbuf++ = (x); \
 4923    }
 4924 
 4925 #define SJ_MODEMINUS(x, y) \
 4926    if(((y) & oldmode->mode) && !((y) & mode.mode)) \
 4927    { \
 4928       INSERTSIGN(-1, '-') \
 4929       *mbuf++ = (x); \
 4930    }
 4931 
 4932 #define SJ_MODEADD(x, y) case (x): mode.mode |= (y); break
 4933 
 4934 #define ADD_PARA(p) para = p; if(pbpos) parabuf[pbpos++] = ' '; \
 4935                      while(*para) parabuf[pbpos++] = *para++; 
 4936 #define ADD_SJBUF(p) para = p; if(sjbufpos) sjbuf[sjbufpos++] = ' '; \
 4937                      while(*para) sjbuf[sjbufpos++] = *para++; 
 4938         
 4939 int m_sjoin(aClient *cptr, aClient *sptr, int parc, char *parv[])
 4940 {
 4941     aChannel    *chptr;
 4942     aClient     *acptr;
 4943     ts_val      newts, oldts, tstosend;
 4944     static Mode mode, *oldmode;
 4945     chanMember  *cm;
 4946     int         args = 0, haveops = 0, keepourmodes = 1, keepnewmodes = 1,
 4947                 what = 0, pargs = 0, fl, people = 0,
 4948                 isnew, clientjoin = 0, pbpos, sjbufpos, created = 0;
 4949     char        *s, *s0, *para;
 4950     static char numeric[16], sjbuf[BUFSIZE];
 4951     char        keep_modebuf[REALMODEBUFLEN], keep_parabuf[REALMODEBUFLEN];
 4952     char        *mbuf = modebuf, *p;
 4953 
 4954     /* if my client is SJOINing, it's just a local user being a dufus. 
 4955      *  Ignore him.
 4956      * parc >= 5 (new serv<->serv SJOIN format)
 4957      * parc >= 6 (old serv<->serv SJOIN format)
 4958      * parc == 3 (new serv<->serv cliSJOIN format)
 4959      */
 4960 
 4961     if (MyClient(sptr) || (parc < 5 && IsServer(sptr)) ||
 4962         (parc < 3 && IsPerson(sptr)))
 4963         return 0;
 4964     
 4965     if(parc == 3 && IsPerson(sptr))
 4966         clientjoin = 1;
 4967     else 
 4968         if(IsDigit(parv[2][0]))
 4969         {
 4970             int i;
 4971             
 4972             if(parc < 6) 
 4973                 return 0;
 4974             
 4975             for(i = 2; i < (parc - 1); i++)
 4976                 parv[i] = parv[i+1];
 4977 
 4978             parc--;
 4979         }
 4980 
 4981     if (!IsChannelName(parv[2]))
 4982         return 0;
 4983 
 4984     newts = atol(parv[1]);
 4985         
 4986     isnew = ChannelExists(parv[2]) ? 0 : 1;
 4987     chptr = get_channel(sptr, parv[2], CREATE, &created);
 4988     oldts = chptr->channelts;
 4989 
 4990     for (cm = chptr->members; cm; cm = cm->next)
 4991         if (cm->flags & MODE_CHANOP)
 4992         {
 4993             haveops++;
 4994             break;
 4995         }
 4996 
 4997     if(clientjoin) /* we have a good old client sjoin, with timestamp */
 4998     {
 4999         if (isnew)
 5000             chptr->channelts = tstosend = newts;
 5001         else if (newts == 0 || oldts == 0)
 5002             chptr->channelts = tstosend = 0;
 5003         else if (newts == oldts)
 5004             tstosend = oldts;
 5005         else if (newts < oldts) 
 5006         {
 5007 #ifdef OLD_WEIRD_CHANOP_NEGOTIATION
 5008             if (haveops)
 5009                 tstosend = oldts;
 5010             else
 5011                 chptr->channelts = tstosend = newts;
 5012 #else
 5013             chptr->channelts = tstosend = newts;
 5014             if (!IsULine(sptr))
 5015             sendto_realops_lev(DEBUG_LEV, "Changing TS for %s from %ld to %ld on"
 5016                                " client SJOIN", chptr->chname, (long)oldts, (long)newts);
 5017 #endif
 5018         }
 5019         else 
 5020             tstosend = oldts;
 5021 
 5022         /* parv[0] is the client that is joining. parv[0] == sptr->name */
 5023 
 5024         if (!IsMember(sptr, chptr)) 
 5025         {
 5026             add_user_to_channel(chptr, sptr, 0);
 5027             joinrate_dojoin(chptr, sptr);
 5028             sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0],
 5029                                    parv[2]);
 5030         }
 5031 
 5032         sendto_serv_butone(cptr, CliSJOINFmt, parv[0], tstosend, parv[2]);
 5033 
 5034         /* if the channel is created in client sjoin, 
 5035          * we lost some channel modes. */
 5036         if(created)
 5037         {
 5038             sendto_realops_lev(DEBUG_LEV, "Requesting resynch of %s from "
 5039                                 "%s (%s!%s@%s[%s] created)", chptr->chname, 
 5040                                 cptr->name, sptr->name, sptr->user->username,
 5041                                 sptr->user->host, sptr->hostip);
 5042             sendto_one(cptr, "RESYNCH %s", chptr->chname);
 5043         }
 5044 
 5045         return 0;
 5046     }
 5047 
 5048     memset((char *) &mode, '\0', sizeof(mode));
 5049 
 5050     s = parv[3];
 5051     while (*s)
 5052     {
 5053         switch (*(s++))
 5054         {
 5055             SJ_MODEADD('i', MODE_INVITEONLY);
 5056             SJ_MODEADD('n', MODE_NOPRIVMSGS);
 5057             SJ_MODEADD('p', MODE_PRIVATE);
 5058             SJ_MODEADD('s', MODE_SECRET);
 5059             SJ_MODEADD('m', MODE_MODERATED);
 5060             SJ_MODEADD('t', MODE_TOPICLIMIT);
 5061             SJ_MODEADD('r', MODE_REGISTERED);
 5062             SJ_MODEADD('R', MODE_REGONLY);
 5063             SJ_MODEADD('M', MODE_MODREG);
 5064             SJ_MODEADD('c', MODE_NOCTRL);
 5065             SJ_MODEADD('O', MODE_OPERONLY);
 5066             SJ_MODEADD('S', MODE_SSLONLY);
 5067             SJ_MODEADD('A', MODE_AUDITORIUM);
 5068             SJ_MODEADD('P', MODE_PRIVACY);
 5069 #ifdef USE_CHANMODE_L
 5070             SJ_MODEADD('L', MODE_LISTED);
 5071 #endif
 5072             case 'k':
 5073                 strncpyzt(mode.key, parv[4 + args], KEYLEN + 1);
 5074                 args++;
 5075                 if (parc < 5 + args)
 5076                     return 0;
 5077                 break;
 5078 
 5079             case 'j':
 5080                 {
 5081                     char *tmpa, *tmpb;
 5082 
 5083                     mode.mode |= MODE_JOINRATE;
 5084                     tmpa = parv[4 + args];
 5085 
 5086                     tmpb = strchr(tmpa, ':');
 5087                     if(tmpb)
 5088                     {
 5089                         *tmpb = '\0';
 5090                         tmpb++;
 5091                         mode.jr_time = atoi(tmpb);
 5092                     }
 5093                     else
 5094                         mode.jr_time = 0;
 5095 
 5096                     mode.jr_num = atoi(tmpa);
 5097                     mode.jrl_size = mode.jr_num * mode.jr_time;
 5098 
 5099                     args++;
 5100                     if (parc < 5 + args)
 5101                         return 0;
 5102                 }
 5103                 break;
 5104 
 5105             case 'l':
 5106                 mode.limit = atoi(parv[4 + args]);
 5107                 args++;
 5108                 if (parc < 5 + args)
 5109                     return 0;
 5110                 break;
 5111         }
 5112     }
 5113 
 5114     oldmode = &chptr->mode;
 5115 
 5116     /* newts is the ts the remote server is providing */ 
 5117     /* oldts is our channel TS */ 
 5118     /* whichever TS is smaller wins. */ 
 5119         
 5120     if (isnew)
 5121         chptr->channelts = tstosend = newts;
 5122     else if (newts == 0 || oldts == 0)
 5123         chptr->channelts = tstosend = 0;
 5124     else if (newts == oldts)
 5125         tstosend = oldts;
 5126 #ifdef OLD_WEIRD_CHANOP_NEGOTIATION
 5127     else if (newts < oldts)
 5128     {