ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/channel_mode.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/channel_mode.c (file contents):
Revision 4800 by michael, Tue Oct 28 13:59:43 2014 UTC vs.
Revision 8044 by michael, Sat Mar 18 16:52:10 2017 UTC

# Line 1 | Line 1
1   /*
2   *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (c) 1997-2014 ircd-hybrid development team
4 > *  Copyright (c) 1997-2017 ircd-hybrid development team
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
# Line 40 | Line 40
40   #include "mempool.h"
41   #include "parse.h"
42  
43 – /* 10 is a magic number in hybrid 6 NFI where it comes from -db */
44 – #define BAN_FUDGE       10
43  
44   static char nuh_mask[MAXPARA][IRCD_BUFSIZE];
47 – /* some buffers for rebuilding channel/nick lists with ,'s */
48 – static char modebuf[IRCD_BUFSIZE];
49 – static char parabuf[MODEBUFLEN];
45   static struct ChModeChange mode_changes[IRCD_BUFSIZE];
46   static unsigned int mode_count;
47   static unsigned int mode_limit;  /* number of modes set other than simple */
# Line 63 | Line 58 | const struct mode_letter chan_modes[] =
58    { MODE_REGISTERED, 'r' },
59    { MODE_SECRET,     's' },
60    { MODE_TOPICLIMIT, 't' },
61 +  { MODE_HIDEBMASKS, 'u' },
62 +  { MODE_NOCTCP,     'C' },
63    { MODE_MODREG,     'M' },
64    { MODE_OPERONLY,   'O' },
65    { MODE_REGONLY,    'R' },
66    { MODE_SSLONLY,    'S' },
67 +  { MODE_NONOTICE,   'T' },
68    { 0, '\0' }
69   };
70  
# Line 83 | Line 81 | const struct mode_letter chan_modes[] =
81   static char *
82   check_string(char *s)
83   {
84 <  char *str = s;
84 >  char *const str = s;
85    static char star[] = "*";
86  
87    if (EmptyString(str))
# Line 102 | Line 100 | check_string(char *s)
100   }
101  
102   /*
103 < * Ban functions to work with mode +b/e/d/I
103 > * Ban functions to work with mode +b/e/I
104   */
105   /* add the specified ID to the channel.
106   *   -is 8/9/00
# Line 111 | Line 109 | check_string(char *s)
109   int
110   add_id(struct Client *client_p, struct Channel *chptr, char *banid, unsigned int type)
111   {
112 <  dlink_list *list = NULL;
113 <  dlink_node *node = NULL;
116 <  struct Ban *banptr = NULL;
117 <  size_t len = 0;
112 >  dlink_list *list;
113 >  dlink_node *node;
114    char name[NICKLEN + 1] = "";
115    char user[USERLEN + 1] = "";
116    char host[HOSTLEN + 1] = "";
# Line 151 | Line 147 | add_id(struct Client *client_p, struct C
147     * Re-assemble a new n!u@h and print it back to banid for sending
148     * the mode to the channel.
149     */
150 <  len = sprintf(banid, "%s!%s@%s", name, user, host);
150 >  size_t len = snprintf(banid, IRCD_BUFSIZE, "%s!%s@%s", name, user, host);
151  
152    switch (type)
153    {
154      case CHFL_BAN:
155        list = &chptr->banlist;
156 <      clear_ban_cache(chptr);
156 >      clear_ban_cache_list(&chptr->locmembers);
157        break;
158      case CHFL_EXCEPTION:
159        list = &chptr->exceptlist;
160 <      clear_ban_cache(chptr);
160 >      clear_ban_cache_list(&chptr->locmembers);
161        break;
162      case CHFL_INVEX:
163        list = &chptr->invexlist;
164        break;
165      default:
166 <      assert(0);
171 <      return 0;
166 >      list = NULL;  /* Let it crash */
167    }
168  
169    DLINK_FOREACH(node, list->head)
170    {
171 <    banptr = node->data;
171 >    const struct Ban *ban = node->data;
172  
173 <    if (!irccmp(banptr->name, name) &&
174 <        !irccmp(banptr->user, user) &&
175 <        !irccmp(banptr->host, host))
173 >    if (!irccmp(ban->name, name) &&
174 >        !irccmp(ban->user, user) &&
175 >        !irccmp(ban->host, host))
176        return 0;
177    }
178  
179 <  banptr = mp_pool_get(ban_pool);
180 <  banptr->name = xstrdup(name);
181 <  banptr->user = xstrdup(user);
182 <  banptr->host = xstrdup(host);
183 <  banptr->when = CurrentTime;
184 <  banptr->len = len - 2;  /* -2 for ! + @ */
185 <  banptr->type = parse_netmask(host, &banptr->addr, &banptr->bits);
179 >  struct Ban *ban = mp_pool_get(ban_pool);
180 >  ban->when = CurrentTime;
181 >  ban->len = len - 2;  /* -2 for ! + @ */
182 >  ban->type = parse_netmask(host, &ban->addr, &ban->bits);
183 >  strlcpy(ban->name, name, sizeof(ban->name));
184 >  strlcpy(ban->user, user, sizeof(ban->user));
185 >  strlcpy(ban->host, host, sizeof(ban->host));
186  
187    if (IsClient(client_p))
188 <  {
189 <    banptr->who = MyCalloc(strlen(client_p->name) +
190 <                           strlen(client_p->username) +
191 <                           strlen(client_p->host) + 3);
197 <    sprintf(banptr->who, "%s!%s@%s", client_p->name,
198 <            client_p->username, client_p->host);
199 <  }
200 <  else if (IsHidden(client_p) || (IsServer(client_p) && ConfigServerHide.hide_servers))
201 <    banptr->who = xstrdup(me.name);
188 >    snprintf(ban->who, sizeof(ban->who), "%s!%s@%s", client_p->name,
189 >             client_p->username, client_p->host);
190 >  else if (IsHidden(client_p) || ConfigServerHide.hide_servers)
191 >    strlcpy(ban->who, me.name, sizeof(ban->who));
192    else
193 <    banptr->who = xstrdup(client_p->name);
193 >    strlcpy(ban->who, client_p->name, sizeof(ban->who));
194  
195 <  dlinkAdd(banptr, &banptr->node, list);
195 >  dlinkAdd(ban, &ban->node, list);
196  
197    return 1;
198   }
# Line 217 | Line 207 | add_id(struct Client *client_p, struct C
207   static int
208   del_id(struct Channel *chptr, char *banid, unsigned int type)
209   {
210 <  dlink_list *list = NULL;
211 <  dlink_node *node = NULL;
210 >  dlink_list *list;
211 >  dlink_node *node;
212    char name[NICKLEN + 1] = "";
213    char user[USERLEN + 1] = "";
214    char host[HOSTLEN + 1] = "";
# Line 241 | Line 231 | del_id(struct Channel *chptr, char *bani
231     * Re-assemble a new n!u@h and print it back to banid for sending
232     * the mode to the channel.
233     */
234 <  sprintf(banid, "%s!%s@%s", name, user, host);
234 >  snprintf(banid, IRCD_BUFSIZE, "%s!%s@%s", name, user, host);
235  
236    switch (type)
237    {
238      case CHFL_BAN:
239        list = &chptr->banlist;
240 <      clear_ban_cache(chptr);
240 >      clear_ban_cache_list(&chptr->locmembers);
241        break;
242      case CHFL_EXCEPTION:
243        list = &chptr->exceptlist;
244 <      clear_ban_cache(chptr);
244 >      clear_ban_cache_list(&chptr->locmembers);
245        break;
246      case CHFL_INVEX:
247        list = &chptr->invexlist;
248        break;
249      default:
250 <      assert(0);
261 <      return 0;
250 >      list = NULL;  /* Let it crash */
251    }
252  
253    DLINK_FOREACH(node, list->head)
254    {
255 <    struct Ban *banptr = node->data;
255 >    struct Ban *ban = node->data;
256  
257 <    if (!irccmp(name, banptr->name) &&
258 <        !irccmp(user, banptr->user) &&
259 <        !irccmp(host, banptr->host))
257 >    if (!irccmp(name, ban->name) &&
258 >        !irccmp(user, ban->user) &&
259 >        !irccmp(host, ban->host))
260      {
261 <      remove_ban(banptr, list);
261 >      remove_ban(ban, list);
262        return 1;
263      }
264    }
# Line 294 | Line 283 | channel_modes(struct Channel *chptr, str
283    *pbuf = '\0';
284  
285    for (const struct mode_letter *tab = chan_modes; tab->mode; ++tab)
286 <    if (chptr->mode.mode & tab->mode)
286 >    if (HasCMode(chptr, tab->mode))
287        *mbuf++ = tab->letter;
288  
289    if (chptr->mode.limit)
290    {
291      *mbuf++ = 'l';
292  
293 <    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
294 <      pbuf += sprintf(pbuf, "%d ", chptr->mode.limit);
293 >    if (IsServer(client_p) || IsMember(client_p, chptr))
294 >      pbuf += sprintf(pbuf, "%u ", chptr->mode.limit);
295    }
296  
297    if (chptr->mode.key[0])
298    {
299      *mbuf++ = 'k';
300  
301 <    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
301 >    if (IsServer(client_p) || IsMember(client_p, chptr))
302        sprintf(pbuf, "%s ", chptr->mode.key);
303    }
304  
# Line 329 | Line 318 | fix_key(char *arg)
318   {
319    unsigned char *s, *t, c;
320  
321 <  for (s = t = (unsigned char *)arg; (c = *s); ++s)
321 >  for (s = t = (unsigned char *)arg; (c = *s) && s - (unsigned char *)arg < KEYLEN; ++s)
322    {
323      c &= 0x7f;
324  
# Line 347 | Line 336 | fix_key(char *arg)
336   * side effects - clear ban cache
337   */
338   void
339 < clear_ban_cache(struct Channel *chptr)
339 > clear_ban_cache_list(dlink_list *list)
340   {
341 <  dlink_node *node = NULL;
341 >  dlink_node *node;
342  
343 <  DLINK_FOREACH(node, chptr->locmembers.head)
355 <  {
356 <    struct Membership *ms = node->data;
357 <    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
358 <  }
359 < }
360 <
361 < void
362 < clear_ban_cache_client(struct Client *client_p)
363 < {
364 <  dlink_node *node = NULL;
365 <
366 <  DLINK_FOREACH(node, client_p->channel.head)
343 >  DLINK_FOREACH(node, list->head)
344    {
345 <    struct Membership *ms = node->data;
346 <    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
345 >    struct Membership *member = node->data;
346 >    member->flags &= ~(CHFL_BAN_SILENCED | CHFL_BAN_CHECKED);
347    }
348   }
349  
# Line 408 | Line 385 | chm_simple(struct Client *source_p, stru
385        sendto_one_numeric(source_p, &me,
386                           alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
387                           ERR_CHANOPRIVSNEEDED, chptr->name);
388 +
389      *errors |= SM_ERR_NOOPS;
390      return;
391    }
# Line 428 | Line 406 | chm_simple(struct Client *source_p, stru
406     */
407    if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
408    {
409 <    chptr->mode.mode |= d;
409 >    AddCMode(chptr, d);
410  
411      mode_changes[mode_count].letter = c;
412      mode_changes[mode_count].arg = NULL;
413      mode_changes[mode_count].id = NULL;
414 +    mode_changes[mode_count].flags = 0;
415      mode_changes[mode_count++].dir = dir;
416    }
417    else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
418    {
419      /* setting - */
420 <
442 <    chptr->mode.mode &= ~d;
420 >    DelCMode(chptr, d);
421  
422      mode_changes[mode_count].letter = c;
423      mode_changes[mode_count].arg = NULL;
424      mode_changes[mode_count].id = NULL;
425 +    mode_changes[mode_count].flags = 0;
426      mode_changes[mode_count++].dir = dir;
427    }
428   }
# Line 458 | Line 437 | chm_registered(struct Client *source_p,
437        sendto_one_numeric(source_p, &me,
438                           alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
439                           ERR_ONLYSERVERSCANCHANGE, chptr->name);
440 +
441      *errors |= SM_ERR_ONLYSERVER;
442      return;
443    }
# Line 478 | Line 458 | chm_registered(struct Client *source_p,
458     */
459    if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
460    {
461 <    chptr->mode.mode |= d;
461 >    AddCMode(chptr, d);
462  
463      mode_changes[mode_count].letter = c;
464      mode_changes[mode_count].arg = NULL;
465      mode_changes[mode_count].id = NULL;
466 +    mode_changes[mode_count].flags = 0;
467      mode_changes[mode_count++].dir = dir;
468    }
469    else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
470    {
471      /* setting - */
472 <
492 <    chptr->mode.mode &= ~d;
472 >    DelCMode(chptr, d);
473  
474      mode_changes[mode_count].letter = c;
475      mode_changes[mode_count].arg = NULL;
476      mode_changes[mode_count].id = NULL;
477 +    mode_changes[mode_count].flags = 0;
478      mode_changes[mode_count++].dir = dir;
479    }
480   }
# Line 502 | Line 483 | static void
483   chm_operonly(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
484               char **parv, int *errors, int alev, int dir, char c, unsigned int d)
485   {
486 <  if (alev < CHACCESS_CHANOP)
486 >  if (alev < CHACCESS_HALFOP)
487    {
488      if (!(*errors & SM_ERR_NOOPS))
489        sendto_one_numeric(source_p, &me,
# Line 530 | Line 511 | chm_operonly(struct Client *source_p, st
511  
512    if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
513    {
514 <    chptr->mode.mode |= d;
514 >    AddCMode(chptr, d);
515  
516      mode_changes[mode_count].letter = c;
517      mode_changes[mode_count].arg = NULL;
518      mode_changes[mode_count].id = NULL;
519 +    mode_changes[mode_count].flags = 0;
520      mode_changes[mode_count++].dir = dir;
521    }
522    else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
523    {
524      /* setting - */
525 <
544 <    chptr->mode.mode &= ~d;
525 >    DelCMode(chptr, d);
526  
527      mode_changes[mode_count].letter = c;
528      mode_changes[mode_count].arg = NULL;
529      mode_changes[mode_count].id = NULL;
530 +    mode_changes[mode_count].flags = 0;
531      mode_changes[mode_count++].dir = dir;
532    }
533   }
# Line 554 | Line 536 | static void
536   chm_ban(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
537          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
538   {
557 –  char *mask = NULL;
558 –
539    if (dir == MODE_QUERY || parc <= *parn)
540    {
541 <    dlink_node *node = NULL;
541 >    dlink_node *node;
542  
543      if (*errors & SM_ERR_RPL_B)
544        return;
# Line 567 | Line 547 | chm_ban(struct Client *source_p, struct
547  
548      DLINK_FOREACH(node, chptr->banlist.head)
549      {
550 <      const struct Ban *banptr = node->data;
551 <      sendto_one_numeric(source_p, &me, RPL_BANLIST, chptr->name,
552 <                         banptr->name, banptr->user, banptr->host,
553 <                         banptr->who, banptr->when);
550 >      const struct Ban *ban = node->data;
551 >
552 >      if (!HasCMode(chptr, MODE_HIDEBMASKS) || alev >= CHACCESS_HALFOP)
553 >        sendto_one_numeric(source_p, &me, RPL_BANLIST, chptr->name,
554 >                           ban->name, ban->user, ban->host,
555 >                           ban->who, ban->when);
556      }
557  
558      sendto_one_numeric(source_p, &me, RPL_ENDOFBANLIST, chptr->name);
# Line 583 | Line 565 | chm_ban(struct Client *source_p, struct
565        sendto_one_numeric(source_p, &me,
566                           alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
567                           ERR_CHANOPRIVSNEEDED, chptr->name);
568 +
569      *errors |= SM_ERR_NOOPS;
570      return;
571    }
# Line 590 | Line 573 | chm_ban(struct Client *source_p, struct
573    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
574      return;
575  
576 <  mask = nuh_mask[*parn];
577 <  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
576 >  char *mask = nuh_mask[*parn];
577 >  strlcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
578    ++(*parn);
579  
580 <  if (!MyConnect(source_p))
581 <    if (strchr(mask, ' '))
599 <      return;
580 >  if (*mask == ':' || (!MyConnect(source_p) && strchr(mask, ' ')))
581 >    return;
582  
583    switch (dir)
584    {
# Line 613 | Line 595 | chm_ban(struct Client *source_p, struct
595    }
596  
597    mode_changes[mode_count].letter = c;
598 <  mode_changes[mode_count].arg = mask;
598 >  mode_changes[mode_count].arg = mask;  /* At this point 'mask' is no longer than NICKLEN + USERLEN + HOSTLEN + 3 */
599    mode_changes[mode_count].id = NULL;
600 +  if (HasCMode(chptr, MODE_HIDEBMASKS))
601 +    mode_changes[mode_count].flags = CHFL_CHANOP | CHFL_HALFOP;
602 +  else
603 +    mode_changes[mode_count].flags = 0;
604    mode_changes[mode_count++].dir = dir;
605   }
606  
# Line 622 | Line 608 | static void
608   chm_except(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
609             char **parv, int *errors, int alev, int dir, char c, unsigned int d)
610   {
625 –  char *mask = NULL;
626 –
611    if (dir == MODE_QUERY || parc <= *parn)
612    {
613 <    dlink_node *node = NULL;
613 >    dlink_node *node;
614  
615      if (*errors & SM_ERR_RPL_E)
616        return;
# Line 635 | Line 619 | chm_except(struct Client *source_p, stru
619  
620      DLINK_FOREACH(node, chptr->exceptlist.head)
621      {
622 <      const struct Ban *banptr = node->data;
622 >      const struct Ban *ban = node->data;
623  
624 <      sendto_one_numeric(source_p, &me, RPL_EXCEPTLIST, chptr->name,
625 <                         banptr->name, banptr->user, banptr->host,
626 <                         banptr->who, banptr->when);
624 >      if (!HasCMode(chptr, MODE_HIDEBMASKS) || alev >= CHACCESS_HALFOP)
625 >        sendto_one_numeric(source_p, &me, RPL_EXCEPTLIST, chptr->name,
626 >                           ban->name, ban->user, ban->host,
627 >                           ban->who, ban->when);
628      }
629  
630      sendto_one_numeric(source_p, &me, RPL_ENDOFEXCEPTLIST, chptr->name);
# Line 652 | Line 637 | chm_except(struct Client *source_p, stru
637        sendto_one_numeric(source_p, &me,
638                           alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
639                           ERR_CHANOPRIVSNEEDED, chptr->name);
640 +
641      *errors |= SM_ERR_NOOPS;
642      return;
643    }
# Line 659 | Line 645 | chm_except(struct Client *source_p, stru
645    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
646      return;
647  
648 <  mask = nuh_mask[*parn];
649 <  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
648 >  char *mask = nuh_mask[*parn];
649 >  strlcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
650    ++(*parn);
651  
652 <  if (!MyConnect(source_p))
653 <    if (strchr(mask, ' '))
668 <      return;
652 >  if (*mask == ':' || (!MyConnect(source_p) && strchr(mask, ' ')))
653 >    return;
654  
655    switch (dir)
656    {
# Line 682 | Line 667 | chm_except(struct Client *source_p, stru
667    }
668  
669    mode_changes[mode_count].letter = c;
670 <  mode_changes[mode_count].arg = mask;
670 >  mode_changes[mode_count].arg = mask;  /* At this point 'mask' is no longer than NICKLEN + USERLEN + HOSTLEN + 3 */
671    mode_changes[mode_count].id = NULL;
672 +  if (HasCMode(chptr, MODE_HIDEBMASKS))
673 +    mode_changes[mode_count].flags = CHFL_CHANOP | CHFL_HALFOP;
674 +  else
675 +    mode_changes[mode_count].flags = 0;
676    mode_changes[mode_count++].dir = dir;
677   }
678  
# Line 691 | Line 680 | static void
680   chm_invex(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
681            char **parv, int *errors, int alev, int dir, char c, unsigned int d)
682   {
694 –  char *mask = NULL;
695 –
683    if (dir == MODE_QUERY || parc <= *parn)
684    {
685 <    dlink_node *node = NULL;
685 >    dlink_node *node;
686  
687      if (*errors & SM_ERR_RPL_I)
688        return;
# Line 704 | Line 691 | chm_invex(struct Client *source_p, struc
691  
692      DLINK_FOREACH(node, chptr->invexlist.head)
693      {
694 <      const struct Ban *banptr = node->data;
694 >      const struct Ban *ban = node->data;
695  
696 <      sendto_one_numeric(source_p, &me, RPL_INVEXLIST, chptr->name,
697 <                         banptr->name, banptr->user, banptr->host,
698 <                         banptr->who, banptr->when);
696 >      if (!HasCMode(chptr, MODE_HIDEBMASKS) || alev >= CHACCESS_HALFOP)
697 >        sendto_one_numeric(source_p, &me, RPL_INVEXLIST, chptr->name,
698 >                           ban->name, ban->user, ban->host,
699 >                           ban->who, ban->when);
700      }
701  
702      sendto_one_numeric(source_p, &me, RPL_ENDOFINVEXLIST, chptr->name);
# Line 721 | Line 709 | chm_invex(struct Client *source_p, struc
709        sendto_one_numeric(source_p, &me,
710                           alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
711                           ERR_CHANOPRIVSNEEDED, chptr->name);
712 +
713      *errors |= SM_ERR_NOOPS;
714      return;
715    }
# Line 728 | Line 717 | chm_invex(struct Client *source_p, struc
717    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
718      return;
719  
720 <  mask = nuh_mask[*parn];
721 <  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
720 >  char *mask = nuh_mask[*parn];
721 >  strlcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
722    ++(*parn);
723  
724 <  if (!MyConnect(source_p))
725 <    if (strchr(mask, ' '))
737 <      return;
724 >  if (*mask == ':' || (!MyConnect(source_p) && strchr(mask, ' ')))
725 >    return;
726  
727    switch (dir)
728    {
# Line 751 | Line 739 | chm_invex(struct Client *source_p, struc
739    }
740  
741    mode_changes[mode_count].letter = c;
742 <  mode_changes[mode_count].arg = mask;
742 >  mode_changes[mode_count].arg = mask;  /* At this point 'mask' is no longer than NICKLEN + USERLEN + HOSTLEN + 3 */
743    mode_changes[mode_count].id = NULL;
744 +  if (HasCMode(chptr, MODE_HIDEBMASKS))
745 +    mode_changes[mode_count].flags = CHFL_CHANOP | CHFL_HALFOP;
746 +  else
747 +    mode_changes[mode_count].flags = 0;
748    mode_changes[mode_count++].dir = dir;
749   }
750  
# Line 769 | Line 761 | chm_voice(struct Client *source_p, struc
761        sendto_one_numeric(source_p, &me,
762                           alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
763                           ERR_CHANOPRIVSNEEDED, chptr->name);
764 +
765      *errors |= SM_ERR_NOOPS;
766      return;
767    }
# Line 783 | Line 776 | chm_voice(struct Client *source_p, struc
776    {
777      if (!(*errors & SM_ERR_NOTONCHANNEL))
778        sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->name);
779 +
780      *errors |= SM_ERR_NOTONCHANNEL;
781      return;
782    }
# Line 790 | Line 784 | chm_voice(struct Client *source_p, struc
784    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
785      return;
786  
787 <  /* no redundant mode changes */
788 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_VOICE))
789 <    return;
790 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_VOICE))
791 <    return;
787 >  switch (dir)
788 >  {
789 >    case MODE_ADD:
790 >      if (has_member_flags(member, CHFL_VOICE))
791 >        return;  /* No redundant mode changes */
792 >
793 >      AddMemberFlag(member, CHFL_VOICE);
794 >      break;
795 >    case MODE_DEL:
796 >      if (!has_member_flags(member, CHFL_VOICE))
797 >        return;  /* No redundant mode changes */
798 >
799 >      DelMemberFlag(member, CHFL_VOICE);
800 >      break;
801 >  }
802  
803    mode_changes[mode_count].letter = c;
804    mode_changes[mode_count].arg = target_p->name;
805    mode_changes[mode_count].id = target_p->id;
806 +  mode_changes[mode_count].flags = 0;
807    mode_changes[mode_count++].dir = dir;
803 –
804 –  if (dir == MODE_ADD)
805 –    AddMemberFlag(member, CHFL_VOICE);
806 –  else
807 –    DelMemberFlag(member, CHFL_VOICE);
808   }
809  
810   static void
# Line 820 | Line 820 | chm_hop(struct Client *source_p, struct
820        sendto_one_numeric(source_p, &me,
821                           alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
822                           ERR_CHANOPRIVSNEEDED, chptr->name);
823 +
824      *errors |= SM_ERR_NOOPS;
825      return;
826    }
# Line 834 | Line 835 | chm_hop(struct Client *source_p, struct
835    {
836      if (!(*errors & SM_ERR_NOTONCHANNEL))
837        sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->name);
838 +
839      *errors |= SM_ERR_NOTONCHANNEL;
840      return;
841    }
# Line 841 | Line 843 | chm_hop(struct Client *source_p, struct
843    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
844      return;
845  
846 <  /* no redundant mode changes */
847 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_HALFOP))
848 <    return;
849 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_HALFOP))
850 <    return;
846 >  switch (dir)
847 >  {
848 >    case MODE_ADD:
849 >      if (has_member_flags(member, CHFL_HALFOP))
850 >        return;  /* No redundant mode changes */
851 >
852 >      AddMemberFlag(member, CHFL_HALFOP);
853 >      break;
854 >    case MODE_DEL:
855 >      if (!has_member_flags(member, CHFL_HALFOP))
856 >        return;  /* No redundant mode changes */
857 >
858 >      DelMemberFlag(member, CHFL_HALFOP);
859 >      break;
860 >  }
861  
862    mode_changes[mode_count].letter = c;
863    mode_changes[mode_count].arg = target_p->name;
864    mode_changes[mode_count].id = target_p->id;
865 +  mode_changes[mode_count].flags = 0;
866    mode_changes[mode_count++].dir = dir;
854 –
855 –  if (dir == MODE_ADD)
856 –    AddMemberFlag(member, CHFL_HALFOP);
857 –  else
858 –    DelMemberFlag(member, CHFL_HALFOP);
867   }
868  
869   static void
# Line 871 | Line 879 | chm_op(struct Client *source_p, struct C
879        sendto_one_numeric(source_p, &me,
880                           alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
881                           ERR_CHANOPRIVSNEEDED, chptr->name);
882 +
883      *errors |= SM_ERR_NOOPS;
884      return;
885    }
# Line 885 | Line 894 | chm_op(struct Client *source_p, struct C
894    {
895      if (!(*errors & SM_ERR_NOTONCHANNEL))
896        sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->name);
897 +
898      *errors |= SM_ERR_NOTONCHANNEL;
899      return;
900    }
# Line 892 | Line 902 | chm_op(struct Client *source_p, struct C
902    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
903      return;
904  
905 <  /* no redundant mode changes */
906 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_CHANOP))
907 <    return;
908 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_CHANOP))
909 <    return;
905 >  switch (dir)
906 >  {
907 >    case MODE_ADD:
908 >      if (has_member_flags(member, CHFL_CHANOP))
909 >        return;  /* No redundant mode changes */
910 >
911 >      AddMemberFlag(member, CHFL_CHANOP);
912 >      break;
913 >    case MODE_DEL:
914 >      if (!has_member_flags(member, CHFL_CHANOP))
915 >        return;  /* No redundant mode changes */
916 >
917 >      DelMemberFlag(member, CHFL_CHANOP);
918 >      break;
919 >  }
920  
921    mode_changes[mode_count].letter = c;
922    mode_changes[mode_count].arg = target_p->name;
923    mode_changes[mode_count].id = target_p->id;
924 +  mode_changes[mode_count].flags = 0;
925    mode_changes[mode_count++].dir = dir;
905 –
906 –  if (dir == MODE_ADD)
907 –    AddMemberFlag(member, CHFL_CHANOP);
908 –  else
909 –    DelMemberFlag(member, CHFL_CHANOP);
926   }
927  
928   static void
929   chm_limit(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
930            char **parv, int *errors, int alev, int dir, char c, unsigned int d)
931   {
916 –  int limit = 0;
917 –
932    if (alev < CHACCESS_HALFOP)
933    {
934      if (!(*errors & SM_ERR_NOOPS))
# Line 930 | Line 944 | chm_limit(struct Client *source_p, struc
944  
945    if (dir == MODE_ADD && parc > *parn)
946    {
947 <    char *lstr = parv[(*parn)++];
947 >    char *const lstr = parv[(*parn)++];
948 >    int limit = 0;
949  
950      if (EmptyString(lstr) || (limit = atoi(lstr)) <= 0)
951        return;
# Line 945 | Line 960 | chm_limit(struct Client *source_p, struc
960      mode_changes[mode_count].letter = c;
961      mode_changes[mode_count].arg = lstr;
962      mode_changes[mode_count].id = NULL;
963 +    mode_changes[mode_count].flags = 0;
964      mode_changes[mode_count++].dir = dir;
965  
966      chptr->mode.limit = limit;
# Line 959 | Line 975 | chm_limit(struct Client *source_p, struc
975      mode_changes[mode_count].letter = c;
976      mode_changes[mode_count].arg = NULL;
977      mode_changes[mode_count].id = NULL;
978 +    mode_changes[mode_count].flags = 0;
979      mode_changes[mode_count++].dir = dir;
980    }
981   }
# Line 982 | Line 999 | chm_key(struct Client *source_p, struct
999  
1000    if (dir == MODE_ADD && parc > *parn)
1001    {
1002 <    char *key = fix_key(parv[(*parn)++]);
1002 >    char *const key = fix_key(parv[(*parn)++]);
1003  
1004      if (EmptyString(key))
1005        return;
# Line 996 | Line 1013 | chm_key(struct Client *source_p, struct
1013          mode_changes[i].letter = 0;
1014  
1015      mode_changes[mode_count].letter = c;
1016 <    mode_changes[mode_count].arg = chptr->mode.key;
1016 >    mode_changes[mode_count].arg = key;
1017      mode_changes[mode_count].id = NULL;
1018 +    mode_changes[mode_count].flags = 0;
1019      mode_changes[mode_count++].dir = dir;
1020    }
1021    else if (dir == MODE_DEL)
# Line 1013 | Line 1031 | chm_key(struct Client *source_p, struct
1031      mode_changes[mode_count].letter = c;
1032      mode_changes[mode_count].arg = "*";
1033      mode_changes[mode_count].id = NULL;
1034 +    mode_changes[mode_count].flags = 0;
1035      mode_changes[mode_count++].dir = dir;
1036    }
1037   }
# Line 1086 | Line 1105 | const struct ChannelMode ModeTable[256]
1105    { chm_nosuch,  0 },                   /* @ */
1106    { chm_nosuch,  0 },                   /* A */
1107    { chm_nosuch,  0 },                   /* B */
1108 <  { chm_nosuch,  0 },                   /* C */
1108 >  { chm_simple,  MODE_NOCTCP },         /* C */
1109    { chm_nosuch,  0 },                   /* D */
1110    { chm_nosuch,  0 },                   /* E */
1111    { chm_nosuch,  0 },                   /* F */
# Line 1103 | Line 1122 | const struct ChannelMode ModeTable[256]
1122    { chm_nosuch,  0 },                   /* Q */
1123    { chm_simple, MODE_REGONLY},          /* R */
1124    { chm_simple, MODE_SSLONLY},          /* S */
1125 <  { chm_nosuch,  0 },                   /* T */
1125 >  { chm_simple, MODE_NONOTICE},         /* T */
1126    { chm_nosuch,  0 },                   /* U */
1127    { chm_nosuch,  0 },                   /* V */
1128    { chm_nosuch,  0 },                   /* W */
# Line 1136 | Line 1155 | const struct ChannelMode ModeTable[256]
1155    { chm_registered, MODE_REGISTERED },  /* r */
1156    { chm_simple,     MODE_SECRET     },  /* s */
1157    { chm_simple,     MODE_TOPICLIMIT },  /* t */
1158 <  { chm_nosuch,     0               },  /* u */
1158 >  { chm_simple,     MODE_HIDEBMASKS },  /* u */
1159    { chm_voice,      0               },  /* v */
1160    { chm_nosuch,     0               },  /* w */
1161    { chm_nosuch,     0               },  /* x */
# Line 1318 | Line 1337 | get_channel_access(const struct Client *
1337   static void
1338   send_mode_changes_server(struct Client *source_p, struct Channel *chptr)
1339   {
1340 <  int mbl = 0, pbl = 0, arglen = 0, nc = 0, mc = 0;
1341 <  int len = 0;
1342 <  int dir = MODE_QUERY;
1343 <  const char *arg = NULL;
1344 <  char *parptr = NULL;
1340 >  char modebuf[IRCD_BUFSIZE] = "";
1341 >  char parabuf[IRCD_BUFSIZE] = "";
1342 >  char *parptr = parabuf;
1343 >  unsigned int mbl = 0, pbl = 0, arglen = 0, modecount = 0, paracount = 0;
1344 >  unsigned int dir = MODE_QUERY;
1345  
1346 <  parabuf[0] = '\0';
1347 <  parptr = parabuf;
1329 <
1330 <  mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %lu %s ", source_p->id,
1331 <                 (unsigned long)chptr->channelts, chptr->name);
1346 >  mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %ju %s ",
1347 >                 source_p->id, chptr->creationtime, chptr->name);
1348  
1349    /* Loop the list of modes we have */
1350 <  for (unsigned i = 0; i < mode_count; ++i)
1350 >  for (unsigned int i = 0; i < mode_count; ++i)
1351    {
1352      if (mode_changes[i].letter == 0)
1353        continue;
1354  
1355 +    const char *arg;
1356      if (mode_changes[i].id)
1357        arg = mode_changes[i].id;
1358      else
# Line 1350 | Line 1367 | send_mode_changes_server(struct Client *
1367       * If we're creeping past the buf size, we need to send it and make
1368       * another line for the other modes
1369       */
1370 <    if ((mc == MAXMODEPARAMS) ||
1371 <        ((arglen + mbl + pbl + 2) > IRCD_BUFSIZE) ||
1355 <        (pbl + arglen + BAN_FUDGE) >= MODEBUFLEN)
1370 >    if ((paracount == MAXMODEPARAMS) ||
1371 >        ((arglen + mbl + pbl + 2 /* +2 for /r/n */ ) > IRCD_BUFSIZE))
1372      {
1373 <      if (nc)
1374 <        sendto_server(source_p, NOCAPS, NOCAPS, "%s %s", modebuf, parabuf);
1373 >      if (modecount)
1374 >        sendto_server(source_p, 0, 0, "%s %s", modebuf, parabuf);
1375  
1376 <      nc = 0;
1377 <      mc = 0;
1376 >      modecount = 0;
1377 >      paracount = 0;
1378  
1379 <      mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %lu %s ", source_p->id,
1380 <                     (unsigned long)chptr->channelts, chptr->name);
1379 >      mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %ju %s ",
1380 >                     source_p->id, chptr->creationtime, chptr->name);
1381  
1382        pbl = 0;
1383        parabuf[0] = '\0';
# Line 1377 | Line 1393 | send_mode_changes_server(struct Client *
1393  
1394      modebuf[mbl++] = mode_changes[i].letter;
1395      modebuf[mbl] = '\0';
1396 <    ++nc;
1396 >    ++modecount;
1397  
1398      if (arg)
1399      {
1400 <      len = sprintf(parptr, "%s ", arg);
1400 >      int len = sprintf(parptr, (pbl == 0) ? "%s" : " %s", arg);
1401        pbl += len;
1402        parptr += len;
1403 <      ++mc;
1403 >      ++paracount;
1404      }
1405    }
1406  
1407 <  if (pbl && parabuf[pbl - 1] == ' ')
1408 <    parabuf[pbl - 1] = '\0';
1393 <
1394 <  if (nc)
1395 <    sendto_server(source_p, NOCAPS, NOCAPS, "%s %s", modebuf, parabuf);
1407 >  if (modecount)
1408 >    sendto_server(source_p, 0, 0, "%s %s", modebuf, parabuf);
1409   }
1410  
1411   /* void send_mode_changes(struct Client *client_p,
# Line 1405 | Line 1418 | send_mode_changes_server(struct Client *
1418   * Side-effects: Sends the appropriate mode changes to other clients
1419   *               and propagates to servers.
1420   */
1408 – /* ensure parabuf < MODEBUFLEN -db */
1421   static void
1422 < send_mode_changes(struct Client *source_p, struct Channel *chptr)
1422 > send_mode_changes_client(struct Client *source_p, struct Channel *chptr)
1423   {
1424 <  int mbl = 0, pbl = 0, arglen = 0, nc = 0, mc = 0;
1413 <  int len = 0;
1414 <  int dir = MODE_QUERY;
1415 <  const char *arg = NULL;
1416 <  char *parptr = NULL;
1417 <
1418 <  /* Bail out if we have nothing to do... */
1419 <  if (!mode_count)
1420 <    return;
1424 >  unsigned int flags = 0;
1425  
1426 <  if (IsServer(source_p))
1423 <    mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1424 <                   ConfigServerHide.hide_servers) ?
1425 <                   me.name : source_p->name, chptr->name);
1426 <  else
1427 <    mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1428 <                   source_p->username, source_p->host, chptr->name);
1429 <
1430 <  parabuf[0] = '\0';
1431 <  parptr = parabuf;
1432 <
1433 <  for (unsigned int i = 0; i < mode_count; ++i)
1426 >  for (unsigned int pass = 2; pass--; flags = CHFL_CHANOP | CHFL_HALFOP)
1427    {
1428 <    if (mode_changes[i].letter == 0)
1429 <      continue;
1430 <
1431 <    arg = mode_changes[i].arg;
1432 <    if (arg)
1433 <      arglen = strlen(arg);
1428 >    char modebuf[IRCD_BUFSIZE] = "";
1429 >    char parabuf[IRCD_BUFSIZE] = "";
1430 >    char *parptr = parabuf;
1431 >    unsigned int mbl = 0, pbl = 0, arglen = 0, modecount = 0, paracount = 0;
1432 >    unsigned int dir = MODE_QUERY;
1433 >
1434 >    if (IsServer(source_p))
1435 >      mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1436 >                     ConfigServerHide.hide_servers) ?
1437 >                     me.name : source_p->name, chptr->name);
1438      else
1439 <      arglen = 0;
1439 >      mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1440 >                     source_p->username, source_p->host, chptr->name);
1441  
1442 <    if ((mc == MAXMODEPARAMS) ||
1445 <        ((arglen + mbl + pbl + 2) > IRCD_BUFSIZE) ||
1446 <        ((arglen + pbl + BAN_FUDGE) >= MODEBUFLEN))
1442 >    for (unsigned int i = 0; i < mode_count; ++i)
1443      {
1444 <      if (mbl && modebuf[mbl - 1] == '-')
1445 <        modebuf[mbl - 1] = '\0';
1450 <
1451 <      if (nc)
1452 <        sendto_channel_local(0, chptr, "%s %s", modebuf, parabuf);
1444 >      if (mode_changes[i].letter == 0 || mode_changes[i].flags != flags)
1445 >        continue;
1446  
1447 <      nc = 0;
1448 <      mc = 0;
1449 <
1457 <      if (IsServer(source_p))
1458 <        mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1459 <                       ConfigServerHide.hide_servers) ?
1460 <                       me.name : source_p->name, chptr->name);
1447 >      const char *arg = mode_changes[i].arg;
1448 >      if (arg)
1449 >        arglen = strlen(arg);
1450        else
1451 <        mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1463 <                       source_p->username, source_p->host, chptr->name);
1451 >        arglen = 0;
1452  
1453 <      pbl = 0;
1454 <      parabuf[0] = '\0';
1455 <      parptr = parabuf;
1456 <      dir = MODE_QUERY;
1457 <    }
1453 >      if ((paracount == MAXMODEPARAMS) ||
1454 >          ((arglen + mbl + pbl + 2 /* +2 for /r/n */ ) > IRCD_BUFSIZE))
1455 >      {
1456 >        if (modecount)
1457 >          sendto_channel_local(NULL, chptr, flags, 0, 0, "%s %s", modebuf, parabuf);
1458  
1459 <    if (dir != mode_changes[i].dir)
1460 <    {
1473 <      modebuf[mbl++] = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
1474 <      dir = mode_changes[i].dir;
1475 <    }
1459 >        modecount = 0;
1460 >        paracount = 0;
1461  
1462 <    modebuf[mbl++] = mode_changes[i].letter;
1463 <    modebuf[mbl] = '\0';
1464 <    ++nc;
1462 >        if (IsServer(source_p))
1463 >          mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1464 >                         ConfigServerHide.hide_servers) ?
1465 >                         me.name : source_p->name, chptr->name);
1466 >        else
1467 >          mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1468 >                         source_p->username, source_p->host, chptr->name);
1469 >
1470 >        pbl = 0;
1471 >        parabuf[0] = '\0';
1472 >        parptr = parabuf;
1473 >        dir = MODE_QUERY;
1474 >      }
1475  
1476 <    if (arg)
1477 <    {
1478 <      len = sprintf(parptr, "%s ", arg);
1479 <      pbl += len;
1480 <      parptr += len;
1486 <      ++mc;
1487 <    }
1488 <  }
1476 >      if (dir != mode_changes[i].dir)
1477 >      {
1478 >        modebuf[mbl++] = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
1479 >        dir = mode_changes[i].dir;
1480 >      }
1481  
1482 <  if (pbl && parabuf[pbl - 1] == ' ')
1483 <    parabuf[pbl - 1] = '\0';
1482 >      modebuf[mbl++] = mode_changes[i].letter;
1483 >      modebuf[mbl] = '\0';
1484 >      ++modecount;
1485  
1486 <  if (nc)
1487 <    sendto_channel_local(0, chptr, "%s %s", modebuf, parabuf);
1486 >      if (arg)
1487 >      {
1488 >        int len = sprintf(parptr, (pbl == 0) ? "%s" : " %s", arg);
1489 >        pbl += len;
1490 >        parptr += len;
1491 >        ++paracount;
1492 >      }
1493 >    }
1494  
1495 <  send_mode_changes_server(source_p, chptr);
1495 >    if (modecount)
1496 >      sendto_channel_local(NULL, chptr, flags, 0, 0, "%s %s", modebuf, parabuf);
1497 >  }
1498   }
1499  
1500   /*
# Line 1543 | Line 1544 | set_channel_mode(struct Client *source_p
1544      }
1545    }
1546  
1547 <  send_mode_changes(source_p, chptr);
1547 >  /* Bail out if we have nothing to do... */
1548 >  if (!mode_count)
1549 >    return;
1550 >
1551 >  send_mode_changes_client(source_p, chptr);
1552 >  send_mode_changes_server(source_p, chptr);
1553   }

Comparing ircd-hybrid/trunk/src/channel_mode.c (property svn:keywords):
Revision 4800 by michael, Tue Oct 28 13:59:43 2014 UTC vs.
Revision 8044 by michael, Sat Mar 18 16:52:10 2017 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

– Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)