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-7.2/src/channel_mode.c (file contents), Revision 371 by michael, Tue Jan 10 10:45:48 2006 UTC vs.
ircd-hybrid/trunk/src/channel_mode.c (file contents), Revision 3724 by michael, Sat May 31 16:27:09 2014 UTC

# Line 1 | Line 1
1   /*
2 < *  ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 < *  channel_mode.c: Controls modes on channels.
2 > *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (C) 2005 by the past and present ircd coders, and others.
4 > *  Copyright (c) 1997-2014 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 18 | Line 17
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
19   *  USA
20 < *
21 < *  $Id$
20 > */
21 >
22 > /*! \file channel_mode.c
23 > * \brief Controls modes on channels.
24 > * \version $Id$
25   */
26  
27   #include "stdinc.h"
28 < #include "tools.h"
28 > #include "list.h"
29   #include "channel.h"
30   #include "channel_mode.h"
31   #include "client.h"
32 < #include "common.h"
31 < #include "hash.h"
32 > #include "conf.h"
33   #include "hostmask.h"
34   #include "irc_string.h"
34 #include "sprintf_irc.h"
35   #include "ircd.h"
36 #include "list.h"
36   #include "numeric.h"
37 < #include "s_serv.h"             /* captab */
39 < #include "s_user.h"
37 > #include "server.h"
38   #include "send.h"
41 #include "whowas.h"
42 #include "s_conf.h"             /* ConfigFileEntry, ConfigChannel */
43 #include "event.h"
39   #include "memory.h"
40 < #include "balloc.h"
41 < #include "s_log.h"
47 <
48 < /* some small utility functions */
49 < static char *check_string(char *);
50 < static char *fix_key(char *);
51 < static char *fix_key_old(char *);
52 < static void chm_nosuch(struct Client *, struct Client *,
53 <                       struct Channel *, int, int *, char **, int *, int,
54 <                       int, char, void *, const char *);
55 < static void chm_simple(struct Client *, struct Client *, struct Channel *,
56 <                       int, int *, char **, int *, int, int, char, void *,
57 <                       const char *);
58 < static void chm_limit(struct Client *, struct Client *, struct Channel *,
59 <                      int, int *, char **, int *, int, int, char, void *,
60 <                      const char *);
61 < static void chm_key(struct Client *, struct Client *, struct Channel *,
62 <                    int, int *, char **, int *, int, int, char, void *,
63 <                    const char *);
64 < static void chm_op(struct Client *, struct Client *, struct Channel *, int,
65 <                   int *, char **, int *, int, int, char, void *,
66 <                   const char *);
67 < #ifdef HALFOPS
68 < static void chm_hop(struct Client *, struct Client *, struct Channel *, int,
69 <                   int *, char **, int *, int, int, char, void *,
70 <                   const char *);
71 < #endif
72 < static void chm_voice(struct Client *, struct Client *, struct Channel *,
73 <                      int, int *, char **, int *, int, int, char, void *,
74 <                      const char *);
75 < static void chm_ban(struct Client *, struct Client *, struct Channel *, int,
76 <                    int *, char **, int *, int, int, char, void *,
77 <                    const char *);
78 < static void chm_except(struct Client *, struct Client *, struct Channel *,
79 <                       int, int *, char **, int *, int, int, char, void *,
80 <                       const char *);
81 < static void chm_invex(struct Client *, struct Client *, struct Channel *,
82 <                      int, int *, char **, int *, int, int, char, void *,
83 <                      const char *);
84 < static void send_cap_mode_changes(struct Client *, struct Client *,
85 <                                  struct Channel *, int, int);
86 < static void send_mode_changes(struct Client *, struct Client *,
87 <                              struct Channel *, char *);
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
91 < #define NCHCAPS         (sizeof(channel_capabs)/sizeof(int))
92 < #define NCHCAP_COMBOS   (1 << NCHCAPS)
44 > #define BAN_FUDGE       10
45  
46 + 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];
50   static struct ChModeChange mode_changes[IRCD_BUFSIZE];
51 < static int mode_count;
52 < static int mode_limit;          /* number of modes set other than simple */
53 < static int simple_modes_mask;   /* bit mask of simple modes already set */
54 < #ifdef HALFOPS
55 < static int channel_capabs[] = { CAP_EX, CAP_IE, CAP_TS6, CAP_HOPS };
56 < #else
57 < static int channel_capabs[] = { CAP_EX, CAP_IE, CAP_TS6 };
58 < #endif
59 < static struct ChCapCombo chcap_combos[NCHCAP_COMBOS];
60 < extern BlockHeap *ban_heap;
51 > static unsigned int mode_count;
52 > static unsigned int mode_limit;  /* number of modes set other than simple */
53 > static unsigned int simple_modes_mask;  /* bit mask of simple modes already set */
54 > extern mp_pool_t *ban_pool;
55 >
56 > const struct mode_letter chan_modes[] =
57 > {
58 >  { MODE_NOCTRL,     'c' },
59 >  { MODE_INVITEONLY, 'i' },
60 >  { MODE_MODERATED,  'm' },
61 >  { MODE_NOPRIVMSGS, 'n' },
62 >  { MODE_PRIVATE,    'p' },
63 >  { MODE_REGISTERED, 'r' },
64 >  { MODE_SECRET,     's' },
65 >  { MODE_TOPICLIMIT, 't' },
66 >  { MODE_MODREG,     'M' },
67 >  { MODE_OPERONLY,   'O' },
68 >  { MODE_REGONLY,    'R' },
69 >  { MODE_SSLONLY,    'S' },
70 >  { 0, '\0' }
71 > };
72  
73  
110 /* XXX check_string is propably not longer required in add_id and del_id */
74   /* check_string()
75   *
76   * inputs       - string to check
# Line 123 | Line 86 | check_string(char *s)
86    char *str = s;
87    static char star[] = "*";
88  
89 <  if (EmptyString(s))
90 <    return (star);
89 >  if (EmptyString(str))
90 >    return star;
91  
92    for (; *s; ++s)
93    {
# Line 135 | Line 98 | check_string(char *s)
98      }
99    }
100  
101 <  return (str);
101 >  return EmptyString(str) ? star : str;
102   }
103  
104   /*
105   * Ban functions to work with mode +b/e/d/I
106   */
107 < /* add the specified ID to the channel..
108 < *   -is 8/9/00
107 > /* add the specified ID to the channel.
108 > *   -is 8/9/00
109   */
110  
111   int
112 < add_id(struct Client *client_p, struct Channel *chptr, char *banid, int type)
112 > add_id(struct Client *client_p, struct Channel *chptr, char *banid, unsigned int type)
113   {
114 <  dlink_list *list;
115 <  dlink_node *ban;
114 >  dlink_list *list = NULL;
115 >  dlink_node *ptr = NULL;
116 >  struct Ban *banptr = NULL;
117    size_t len = 0;
118 <  struct Ban *actualBan;
119 <  unsigned int num_mask;
120 <  char *name = NULL, *user = NULL, *host = NULL;
118 >  char name[NICKLEN + 1] = "";
119 >  char user[USERLEN + 1] = "";
120 >  char host[HOSTLEN + 1] = "";
121 >  struct split_nuh_item nuh;
122  
123 <  /* dont let local clients overflow the b/e/I lists */
123 >  /* Don't let local clients overflow the b/e/I lists */
124    if (MyClient(client_p))
125    {
126 <    num_mask = dlink_list_length(&chptr->banlist) +
127 <               dlink_list_length(&chptr->exceptlist) +
128 <               dlink_list_length(&chptr->invexlist);
126 >    unsigned int num_mask = dlink_list_length(&chptr->banlist) +
127 >                            dlink_list_length(&chptr->exceptlist) +
128 >                            dlink_list_length(&chptr->invexlist);
129  
130      if (num_mask >= ConfigChannel.max_bans)
131      {
132 <      sendto_one(client_p, form_str(ERR_BANLISTFULL),
168 <                 me.name, client_p->name, chptr->chname, banid);
132 >      sendto_one_numeric(client_p, &me, ERR_BANLISTFULL, chptr->chname, banid);
133        return 0;
134      }
135  
136      collapse(banid);
137    }
138  
139 <  split_nuh(check_string(banid), &name, &user, &host);
139 >  nuh.nuhmask  = check_string(banid);
140 >  nuh.nickptr  = name;
141 >  nuh.userptr  = user;
142 >  nuh.hostptr  = host;
143 >
144 >  nuh.nicksize = sizeof(name);
145 >  nuh.usersize = sizeof(user);
146 >  nuh.hostsize = sizeof(host);
147 >
148 >  split_nuh(&nuh);
149  
150    /*
151 <   * Assemble a n!u@h and print it back to banid for sending
151 >   * Re-assemble a new n!u@h and print it back to banid for sending
152     * the mode to the channel.
153     */
154 <  len = ircsprintf(banid, "%s!%s@%s", name, user, host);
154 >  len = sprintf(banid, "%s!%s@%s", name, user, host);
155  
156    switch (type)
157    {
# Line 198 | Line 171 | add_id(struct Client *client_p, struct C
171        return 0;
172    }
173  
174 <  DLINK_FOREACH(ban, list->head)
174 >  DLINK_FOREACH(ptr, list->head)
175    {
176 <    actualBan = ban->data;
177 <    if (!irccmp(actualBan->name, name) &&
178 <        !irccmp(actualBan->username, user) &&
179 <        !irccmp(actualBan->host, host))
180 <    {
208 <      MyFree(name);
209 <      MyFree(user);
210 <      MyFree(host);
176 >    banptr = ptr->data;
177 >
178 >    if (!irccmp(banptr->name, name) &&
179 >        !irccmp(banptr->user, user) &&
180 >        !irccmp(banptr->host, host))
181        return 0;
212    }
182    }
183  
184 <  actualBan = BlockHeapAlloc(ban_heap);
185 <  actualBan->when = CurrentTime;
186 <  actualBan->name = name;
187 <  actualBan->username = user;
188 <  actualBan->host = host;
189 <  actualBan->len = len-2; /* -2 for @ and ! */
190 <  actualBan->type = parse_netmask(host, &actualBan->addr, &actualBan->bits);
184 >  banptr = mp_pool_get(ban_pool);
185 >  memset(banptr, 0, sizeof(*banptr));
186 >
187 >  banptr->name = xstrdup(name);
188 >  banptr->user = xstrdup(user);
189 >  banptr->host = xstrdup(host);
190 >  banptr->when = CurrentTime;
191 >  banptr->len = len - 2;  /* -2 for @ and ! */
192 >  banptr->type = parse_netmask(host, &banptr->addr, &banptr->bits);
193  
194    if (IsClient(client_p))
195    {
196 <    actualBan->who =
197 <      MyMalloc(strlen(client_p->name) +
198 <               strlen(client_p->username) +
199 <               strlen(client_p->host) + 3);
200 <    ircsprintf(actualBan->who, "%s!%s@%s",
230 <               client_p->name, client_p->username, client_p->host);
196 >    banptr->who = MyCalloc(strlen(client_p->name) +
197 >                           strlen(client_p->username) +
198 >                           strlen(client_p->host) + 3);
199 >    sprintf(banptr->who, "%s!%s@%s", client_p->name,
200 >            client_p->username, client_p->host);
201    }
202 +  else if (IsHidden(client_p) || (IsServer(client_p) && ConfigServerHide.hide_servers))
203 +    banptr->who = xstrdup(me.name);
204    else
205 <    DupString(actualBan->who, client_p->name);
205 >    banptr->who = xstrdup(client_p->name);
206  
207 <  dlinkAdd(actualBan, &actualBan->node, list);
207 >  dlinkAdd(banptr, &banptr->node, list);
208  
209    return 1;
210   }
# Line 245 | Line 217 | add_id(struct Client *client_p, struct C
217   * side effects -
218   */
219   static int
220 < del_id(struct Channel *chptr, char *banid, int type)
220 > del_id(struct Channel *chptr, char *banid, unsigned int type)
221   {
222 <  dlink_list *list;
223 <  dlink_node *ban;
224 <  struct Ban *banptr;
225 <  char *name = NULL, *user = NULL, *host = NULL;
226 <
227 <  if (banid == NULL)
228 <    return 0;
222 >  dlink_list *list = NULL;
223 >  dlink_node *ptr = NULL;
224 >  char name[NICKLEN + 1] = "";
225 >  char user[USERLEN + 1] = "";
226 >  char host[HOSTLEN + 1] = "";
227 >  struct split_nuh_item nuh;
228 >
229 >  assert(banid);
230 >
231 >  nuh.nuhmask  = check_string(banid);
232 >  nuh.nickptr  = name;
233 >  nuh.userptr  = user;
234 >  nuh.hostptr  = host;
235 >
236 >  nuh.nicksize = sizeof(name);
237 >  nuh.usersize = sizeof(user);
238 >  nuh.hostsize = sizeof(host);
239  
240 <  split_nuh(check_string(banid), &name, &user, &host);
240 >  split_nuh(&nuh);
241  
242    /*
243 <   * Assemble a n!u@h and print it back to banid for sending
243 >   * Re-assemble a new n!u@h and print it back to banid for sending
244     * the mode to the channel.
245     */
246 <  ircsprintf(banid, "%s!%s@%s", name, user, host);
246 >  sprintf(banid, "%s!%s@%s", name, user, host);
247  
248    switch (type)
249    {
# Line 277 | Line 259 | del_id(struct Channel *chptr, char *bani
259        list = &chptr->invexlist;
260        break;
261      default:
262 <      sendto_realops_flags(UMODE_ALL, L_ALL,
263 <                           "del_id() called with unknown ban type %d!", type);
282 <      MyFree(name);
283 <      MyFree(user);
284 <      MyFree(host);
285 <      return(0);
262 >      assert(0);
263 >      return 0;
264    }
265  
266 <  DLINK_FOREACH(ban, list->head)
266 >  DLINK_FOREACH(ptr, list->head)
267    {
268 <    banptr = ban->data;
268 >    struct Ban *banptr = ptr->data;
269  
270      if (!irccmp(name, banptr->name) &&
271 <        !irccmp(user, banptr->username) &&
272 <        !irccmp(host, banptr->host))
271 >        !irccmp(user, banptr->user) &&
272 >        !irccmp(host, banptr->host))
273      {
274        remove_ban(banptr, list);
297      MyFree(name);
298      MyFree(user);
299      MyFree(host);
275        return 1;
276      }
277    }
278  
304  MyFree(name);
305  MyFree(user);
306  MyFree(host);
279    return 0;
280   }
281  
310 static const struct mode_letter
311 {
312  const unsigned int mode;
313  const unsigned char letter;
314 } flags[] = {
315  { MODE_INVITEONLY, 'i' },
316  { MODE_MODERATED,  'm' },
317  { MODE_NOPRIVMSGS, 'n' },
318  { MODE_PRIVATE,    'p' },
319  { MODE_SECRET,     's' },
320  { MODE_TOPICLIMIT, 't' },
321  { 0, '\0' }
322 };
323
282   /* channel_modes()
283   *
284   * inputs       - pointer to channel
# Line 332 | Line 290 | static const struct mode_letter
290   * chptr onto buffer mbuf with the parameters in pbuf.
291   */
292   void
293 < channel_modes(struct Channel *chptr, struct Client *client_p,
336 <              char *mbuf, char *pbuf)
293 > channel_modes(struct Channel *chptr, struct Client *client_p, char *mbuf, char *pbuf)
294   {
338  int i;
339
295    *mbuf++ = '+';
296    *pbuf = '\0';
297  
298 <  for (i = 0; flags[i].mode; ++i)
299 <    if (chptr->mode.mode & flags[i].mode)
300 <      *mbuf++ = flags[i].letter;
298 >  for (const struct mode_letter *tab = chan_modes; tab->mode; ++tab)
299 >    if (chptr->mode.mode & tab->mode)
300 >      *mbuf++ = tab->letter;
301  
302    if (chptr->mode.limit)
303    {
304      *mbuf++ = 'l';
305  
306 <    if (IsMember(client_p, chptr) || IsServer(client_p))
307 <      pbuf += ircsprintf(pbuf, "%d ", chptr->mode.limit);
306 >    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
307 >      pbuf += sprintf(pbuf, "%d ", chptr->mode.limit);
308    }
309  
310    if (chptr->mode.key[0])
311    {
312      *mbuf++ = 'k';
313  
314 <    if (*pbuf || IsMember(client_p, chptr) || IsServer(client_p))
315 <      ircsprintf(pbuf, "%s ", chptr->mode.key);
314 >    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
315 >      sprintf(pbuf, "%s ", chptr->mode.key);
316    }
317  
318    *mbuf = '\0';
319   }
320  
321   /* fix_key()
322 < *
322 > *
323   * inputs       - pointer to key to clean up
324   * output       - pointer to cleaned up key
325   * side effects - input string is modified
# Line 376 | Line 331 | fix_key(char *arg)
331   {
332    unsigned char *s, *t, c;
333  
334 <  for (s = t = (unsigned char *)arg; (c = *s); s++)
334 >  for (s = t = (unsigned char *)arg; (c = *s); ++s)
335    {
336      c &= 0x7f;
337 +
338      if (c != ':' && c > ' ' && c != ',')
339        *t++ = c;
340    }
341  
342    *t = '\0';
343 <  return(arg);
343 >  return arg;
344   }
345  
346   /* fix_key_old()
347 < *
347 > *
348   * inputs       - pointer to key to clean up
349   * output       - pointer to cleaned up key
350 < * side effects - input string is modifed
350 > * side effects - input string is modifed
351   *
352   * Here we attempt to be compatible with older non-hybrid servers.
353   * We can't back down from the ':' issue however.  --Rodder
# Line 401 | Line 357 | fix_key_old(char *arg)
357   {
358    unsigned char *s, *t, c;
359  
360 <  for (s = t = (unsigned char *)arg; (c = *s); s++)
360 >  for (s = t = (unsigned char *)arg; (c = *s); ++s)
361    {
362      c &= 0x7f;
363 <    if ((c != 0x0a) && (c != ':') && (c != 0x0d) && (c != ','))
363 >
364 >    if ((c != 0x0a) && (c != ':') &&
365 >        (c != 0x0d) && (c != ','))
366        *t++ = c;
367    }
368  
369    *t = '\0';
370 <  return(arg);
370 >  return arg;
371   }
372  
373 < /* bitmasks for various error returns that set_channel_mode should only return
374 < * once per call  -orabidoo
375 < */
376 <
419 < #define SM_ERR_NOTS         0x00000001 /* No TS on channel  */
420 < #define SM_ERR_NOOPS        0x00000002 /* No chan ops       */
421 < #define SM_ERR_UNKNOWN      0x00000004
422 < #define SM_ERR_RPL_B        0x00000008
423 < #define SM_ERR_RPL_E        0x00000010
424 < #define SM_ERR_NOTONCHANNEL 0x00000020 /* Not on channel    */
425 < #define SM_ERR_RPL_I        0x00000040
426 <
427 < /* Now lets do some stuff to keep track of what combinations of
428 < * servers exist...
429 < * Note that the number of combinations doubles each time you add
430 < * something to this list. Each one is only quick if no servers use that
431 < * combination, but if the numbers get too high here MODE will get too
432 < * slow. I suggest if you get more than 7 here, you consider getting rid
433 < * of some and merging or something. If it wasn't for irc+cs we would
434 < * probably not even need to bother about most of these, but unfortunately
435 < * we do. -A1kmm
436 < */
437 <
438 < /* void init_chcap_usage_counts(void)
439 < *
440 < * Inputs       - none
441 < * Output       - none
442 < * Side-effects - Initialises the usage counts to zero. Fills in the
443 < *                chcap_yes and chcap_no combination tables.
373 > /*
374 > * inputs       - pointer to channel
375 > * output       - none
376 > * side effects - clear ban cache
377   */
378   void
379 < init_chcap_usage_counts(void)
379 > clear_ban_cache(struct Channel *chptr)
380   {
381 <  unsigned long m, c, y, n;
449 <
450 <  memset(chcap_combos, 0, sizeof(chcap_combos));
381 >  dlink_node *ptr = NULL;
382  
383 <  /* For every possible combination */
453 <  for (m = 0; m < NCHCAP_COMBOS; m++)
383 >  DLINK_FOREACH(ptr, chptr->members.head)
384    {
385 <    /* Check each capab */
386 <    for (c = y = n = 0; c < NCHCAPS; c++)
387 <    {
388 <      if ((m & (1 << c)) == 0)
459 <        n |= channel_capabs[c];
460 <      else
461 <        y |= channel_capabs[c];
462 <    }
463 <    chcap_combos[m].cap_yes = y;
464 <    chcap_combos[m].cap_no  = n;
385 >    struct Membership *ms = ptr->data;
386 >
387 >    if (MyConnect(ms->client_p))
388 >      ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
389    }
390   }
391  
468 /* void set_chcap_usage_counts(struct Client *serv_p)
469 * Input: serv_p; The client whose capabs to register.
470 * Output: none
471 * Side-effects: Increments the usage counts for the correct capab
472 *               combination.
473 */
392   void
393 < set_chcap_usage_counts(struct Client *serv_p)
393 > clear_ban_cache_client(struct Client *client_p)
394   {
395 <  int n;
395 >  dlink_node *ptr = NULL;
396  
397 <  for (n = 0; n < NCHCAP_COMBOS; n++)
397 >  DLINK_FOREACH(ptr, client_p->channel.head)
398    {
399 <    if (((serv_p->localClient->caps & chcap_combos[n].cap_yes) ==
400 <         chcap_combos[n].cap_yes) &&
483 <        ((serv_p->localClient->caps & chcap_combos[n].cap_no) == 0))
484 <    {
485 <      chcap_combos[n].count++;
486 <      return;
487 <    }
399 >    struct Membership *ms = ptr->data;
400 >    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
401    }
489
490  /* This should be impossible -A1kmm. */
491  assert(0);
402   }
403  
404 < /* void set_chcap_usage_counts(struct Client *serv_p)
405 < *
406 < * Inputs       - serv_p; The client whose capabs to register.
497 < * Output       - none
498 < * Side-effects - Decrements the usage counts for the correct capab
499 < *                combination.
404 > /*
405 > * Bitmasks for various error returns that set_channel_mode should only return
406 > * once per call  -orabidoo
407   */
408 < void
502 < unset_chcap_usage_counts(struct Client *serv_p)
408 > enum
409   {
410 <  int n;
411 <
412 <  for (n = 0; n < NCHCAP_COMBOS; n++)
413 <  {
414 <    if ((serv_p->localClient->caps & chcap_combos[n].cap_yes) ==
415 <        chcap_combos[n].cap_yes &&
416 <        (serv_p->localClient->caps & chcap_combos[n].cap_no) == 0)
417 <    {
418 <      /* Hopefully capabs can't change dynamically or anything... */
513 <      assert(chcap_combos[n].count > 0);
514 <      chcap_combos[n].count--;
515 <      return;
516 <    }
517 <  }
518 <
519 <  /* This should be impossible -A1kmm. */
520 <  assert(0);
521 < }
410 >  SM_ERR_NOOPS        = 1 << 0,  /* No chan ops */
411 >  SM_ERR_UNKNOWN      = 1 << 1,
412 >  SM_ERR_RPL_B        = 1 << 2,
413 >  SM_ERR_RPL_E        = 1 << 3,
414 >  SM_ERR_RPL_I        = 1 << 4,
415 >  SM_ERR_NOTONCHANNEL = 1 << 5,  /* Client is not on channel */
416 >  SM_ERR_NOTOPER      = 1 << 6,
417 >  SM_ERR_ONLYSERVER   = 1 << 7
418 > };
419  
420   /* Mode functions handle mode changes for a particular mode... */
421   static void
422 < chm_nosuch(struct Client *client_p, struct Client *source_p,
423 <           struct Channel *chptr, int parc, int *parn,
527 <           char **parv, int *errors, int alev, int dir, char c, void *d,
528 <           const char *chname)
422 > chm_nosuch(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
423 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
424   {
425    if (*errors & SM_ERR_UNKNOWN)
426      return;
427  
428    *errors |= SM_ERR_UNKNOWN;
429 <  sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name,
535 <             source_p->name, c);
429 >  sendto_one_numeric(source_p, &me, ERR_UNKNOWNMODE, c);
430   }
431  
432   static void
433 < chm_simple(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
434 <           int parc, int *parn, char **parv, int *errors, int alev, int dir,
541 <           char c, void *d, const char *chname)
433 > chm_simple(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
434 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
435   {
436 <  long mode_type;
436 >  if (alev < CHACCESS_HALFOP)
437 >  {
438 >    if (!(*errors & SM_ERR_NOOPS))
439 >      sendto_one_numeric(source_p, &me,
440 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
441 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
442 >    *errors |= SM_ERR_NOOPS;
443 >    return;
444 >  }
445 >
446 >  /* If have already dealt with this simple mode, ignore it */
447 >  if (simple_modes_mask & d)
448 >    return;
449  
450 <  mode_type = (long)d;
450 >  simple_modes_mask |= d;
451 >
452 >  /* setting + */
453 >  /* Apparently, (though no one has ever told the hybrid group directly)
454 >   * admins don't like redundant mode checking. ok. It would have been nice
455 >   * if you had have told us directly. I've left the original code snippets
456 >   * in place.
457 >   *
458 >   * -Dianora
459 >   */
460 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
461 >  {
462 >    chptr->mode.mode |= d;
463 >
464 >    mode_changes[mode_count].letter = c;
465 >    mode_changes[mode_count].dir = MODE_ADD;
466 >    mode_changes[mode_count].id = NULL;
467 >    mode_changes[mode_count].mems = ALL_MEMBERS;
468 >    mode_changes[mode_count++].arg = NULL;
469 >  }
470 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
471 >  {
472 >    /* setting - */
473 >
474 >    chptr->mode.mode &= ~d;
475 >
476 >    mode_changes[mode_count].letter = c;
477 >    mode_changes[mode_count].dir = MODE_DEL;
478 >    mode_changes[mode_count].mems = ALL_MEMBERS;
479 >    mode_changes[mode_count].id = NULL;
480 >    mode_changes[mode_count++].arg = NULL;
481 >  }
482 > }
483 >
484 > static void
485 > chm_registered(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
486 >               char **parv, int *errors, int alev, int dir, char c, unsigned int d)
487 > {
488 >  if (!IsServer(source_p) && !HasFlag(source_p, FLAGS_SERVICE))
489 >  {
490 >    if (!(*errors & SM_ERR_ONLYSERVER))
491 >      sendto_one_numeric(source_p, &me,
492 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
493 >                         ERR_ONLYSERVERSCANCHANGE, chptr->chname);
494 >    *errors |= SM_ERR_ONLYSERVER;
495 >    return;
496 >  }
497 >
498 >  /* If have already dealt with this simple mode, ignore it */
499 >  if (simple_modes_mask & d)
500 >    return;
501 >
502 >  simple_modes_mask |= d;
503 >
504 >  /* setting + */
505 >  /* Apparently, (though no one has ever told the hybrid group directly)
506 >   * admins don't like redundant mode checking. ok. It would have been nice
507 >   * if you had have told us directly. I've left the original code snippets
508 >   * in place.
509 >   *
510 >   * -Dianora
511 >   */
512 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
513 >  {
514 >    chptr->mode.mode |= d;
515 >
516 >    mode_changes[mode_count].letter = c;
517 >    mode_changes[mode_count].dir = MODE_ADD;
518 >    mode_changes[mode_count].id = NULL;
519 >    mode_changes[mode_count].mems = ALL_MEMBERS;
520 >    mode_changes[mode_count++].arg = NULL;
521 >  }
522 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
523 >  {
524 >    /* setting - */
525 >
526 >    chptr->mode.mode &= ~d;
527 >
528 >    mode_changes[mode_count].letter = c;
529 >    mode_changes[mode_count].dir = MODE_DEL;
530 >    mode_changes[mode_count].mems = ALL_MEMBERS;
531 >    mode_changes[mode_count].id = NULL;
532 >    mode_changes[mode_count++].arg = NULL;
533 >  }
534 > }
535  
536 <  if ((alev < CHACCESS_HALFOP) ||
537 <      ((mode_type == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
536 > static void
537 > chm_operonly(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
538 >             char **parv, int *errors, int alev, int dir, char c, unsigned int d)
539 > {
540 >  if (alev < CHACCESS_CHANOP)
541    {
542      if (!(*errors & SM_ERR_NOOPS))
543 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
544 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
545 <                 me.name, source_p->name, chname);
543 >      sendto_one_numeric(source_p, &me,
544 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
545 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
546 >
547      *errors |= SM_ERR_NOOPS;
548      return;
549    }
550  
551 +  if (MyClient(source_p) && !HasUMode(source_p, UMODE_OPER))
552 +  {
553 +    if (!(*errors & SM_ERR_NOTOPER))
554 +      sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
555 +
556 +    *errors |= SM_ERR_NOTOPER;
557 +    return;
558 +  }
559 +
560    /* If have already dealt with this simple mode, ignore it */
561 <  if (simple_modes_mask & mode_type)
561 >  if (simple_modes_mask & d)
562      return;
563  
564 <  simple_modes_mask |= mode_type;
564 >  simple_modes_mask |= d;
565  
566 <  /* setting + */
565 <  /* Apparently, (though no one has ever told the hybrid group directly)
566 <   * admins don't like redundant mode checking. ok. It would have been nice
567 <   * if you had have told us directly. I've left the original code snippets
568 <   * in place.
569 <   *
570 <   * -Dianora
571 <   */
572 <  if ((dir == MODE_ADD)) /* && !(chptr->mode.mode & mode_type)) */
566 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
567    {
568 <    chptr->mode.mode |= mode_type;
568 >    chptr->mode.mode |= d;
569  
570      mode_changes[mode_count].letter = c;
571      mode_changes[mode_count].dir = MODE_ADD;
578    mode_changes[mode_count].caps = 0;
579    mode_changes[mode_count].nocaps = 0;
572      mode_changes[mode_count].id = NULL;
573      mode_changes[mode_count].mems = ALL_MEMBERS;
574      mode_changes[mode_count++].arg = NULL;
575    }
576 <  else if ((dir == MODE_DEL)) /* && (chptr->mode.mode & mode_type)) */
576 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
577    {
578      /* setting - */
579  
580 <    chptr->mode.mode &= ~mode_type;
580 >    chptr->mode.mode &= ~d;
581  
582      mode_changes[mode_count].letter = c;
583      mode_changes[mode_count].dir = MODE_DEL;
592    mode_changes[mode_count].caps = 0;
593    mode_changes[mode_count].nocaps = 0;
584      mode_changes[mode_count].mems = ALL_MEMBERS;
585      mode_changes[mode_count].id = NULL;
586      mode_changes[mode_count++].arg = NULL;
# Line 598 | Line 588 | chm_simple(struct Client *client_p, stru
588   }
589  
590   static void
591 < chm_ban(struct Client *client_p, struct Client *source_p,
592 <        struct Channel *chptr, int parc, int *parn,
603 <        char **parv, int *errors, int alev, int dir, char c, void *d,
604 <        const char *chname)
591 > chm_ban(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
592 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
593   {
594    char *mask = NULL;
595  
# Line 617 | Line 605 | chm_ban(struct Client *client_p, struct
605      DLINK_FOREACH(ptr, chptr->banlist.head)
606      {
607        const struct Ban *banptr = ptr->data;
608 <      sendto_one(client_p, form_str(RPL_BANLIST),
609 <                 me.name, client_p->name, chname,
610 <                 banptr->name, banptr->username, banptr->host,
623 <                 banptr->who, banptr->when);
608 >      sendto_one_numeric(source_p, &me, RPL_BANLIST, chptr->chname,
609 >                         banptr->name, banptr->user, banptr->host,
610 >                         banptr->who, banptr->when);
611      }
612  
613 <    sendto_one(source_p, form_str(RPL_ENDOFBANLIST), me.name,
627 <               source_p->name, chname);
613 >    sendto_one_numeric(source_p, &me, RPL_ENDOFBANLIST, chptr->chname);
614      return;
615    }
616  
617    if (alev < CHACCESS_HALFOP)
618    {
619      if (!(*errors & SM_ERR_NOOPS))
620 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
621 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
622 <                 me.name, source_p->name, chname);
620 >      sendto_one_numeric(source_p, &me,
621 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
622 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
623      *errors |= SM_ERR_NOOPS;
624      return;
625    }
# Line 641 | Line 627 | chm_ban(struct Client *client_p, struct
627    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
628      return;
629  
630 <  mask = parv[(*parn)++];
631 <  
632 <  if (IsServer(client_p))
630 >  mask = nuh_mask[*parn];
631 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
632 >  ++*parn;
633 >
634 >  if (!MyConnect(source_p))
635      if (strchr(mask, ' '))
636        return;
637  
# Line 654 | Line 642 | chm_ban(struct Client *client_p, struct
642          return;
643        break;
644      case MODE_DEL:
657 /* XXX grrrrrrr */
658 #ifdef NO_BAN_COOKIE
645        if (!del_id(chptr, mask, CHFL_BAN))
646          return;
661 #else
662     /* XXX this hack allows /mode * +o-b nick ban.cookie
663      * I'd like to see this hack go away in the future.
664      */
665      del_id(chptr, mask, CHFL_BAN);
666 #endif
647        break;
648      default:
649        assert(0);
# Line 671 | Line 651 | chm_ban(struct Client *client_p, struct
651  
652    mode_changes[mode_count].letter = c;
653    mode_changes[mode_count].dir = dir;
674  mode_changes[mode_count].caps = 0;
675  mode_changes[mode_count].nocaps = 0;
654    mode_changes[mode_count].mems = ALL_MEMBERS;
655    mode_changes[mode_count].id = NULL;
656    mode_changes[mode_count++].arg = mask;
657   }
658  
659   static void
660 < chm_except(struct Client *client_p, struct Client *source_p,
661 <           struct Channel *chptr, int parc, int *parn,
684 <           char **parv, int *errors, int alev, int dir, char c, void *d,
685 <           const char *chname)
660 > chm_except(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
661 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
662   {
663    char *mask = NULL;
664  
689  /* if we have +e disabled, allow local clients to do anything but
690   * set the mode.  This prevents the abuse of +e when just a few
691   * servers support it. --fl
692   */
693  if (!ConfigChannel.use_except && MyClient(source_p) &&
694      ((dir == MODE_ADD) && (parc > *parn)))
695  {
696    if (*errors & SM_ERR_RPL_E)
697      return;
698
699    *errors |= SM_ERR_RPL_E;
700    return;
701  }
702
665    if (alev < CHACCESS_HALFOP)
666    {
667      if (!(*errors & SM_ERR_NOOPS))
668 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
669 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
670 <                 me.name, source_p->name, chname);
668 >      sendto_one_numeric(source_p, &me,
669 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
670 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
671      *errors |= SM_ERR_NOOPS;
672      return;
673    }
# Line 722 | Line 684 | chm_except(struct Client *client_p, stru
684      DLINK_FOREACH(ptr, chptr->exceptlist.head)
685      {
686        const struct Ban *banptr = ptr->data;
687 <      sendto_one(client_p, form_str(RPL_EXCEPTLIST),
688 <                 me.name, client_p->name, chname,
689 <                 banptr->name, banptr->username, banptr->host,
690 <                 banptr->who, banptr->when);
687 >
688 >      sendto_one_numeric(source_p, &me, RPL_EXCEPTLIST, chptr->chname,
689 >                         banptr->name, banptr->user, banptr->host,
690 >                         banptr->who, banptr->when);
691      }
692  
693 <    sendto_one(source_p, form_str(RPL_ENDOFEXCEPTLIST), me.name,
732 <               source_p->name, chname);
693 >    sendto_one_numeric(source_p, &me, RPL_ENDOFEXCEPTLIST, chptr->chname);
694      return;
695    }
696  
697    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
698      return;
699  
700 <  mask = parv[(*parn)++];
700 >  mask = nuh_mask[*parn];
701 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
702 >  ++*parn;
703  
704 <  if (IsServer(client_p))
704 >  if (!MyConnect(source_p))
705      if (strchr(mask, ' '))
706        return;
707  
# Line 758 | Line 721 | chm_except(struct Client *client_p, stru
721  
722    mode_changes[mode_count].letter = c;
723    mode_changes[mode_count].dir = dir;
724 <  mode_changes[mode_count].caps = CAP_EX;
762 <  mode_changes[mode_count].nocaps = 0;
763 <
764 <  if (ConfigChannel.use_except)
765 <    mode_changes[mode_count].mems = ONLY_CHANOPS;
766 <  else
767 <    mode_changes[mode_count].mems = ONLY_SERVERS;
768 <
724 >  mode_changes[mode_count].mems = ONLY_CHANOPS;
725    mode_changes[mode_count].id = NULL;
726    mode_changes[mode_count++].arg = mask;
727   }
728  
729   static void
730 < chm_invex(struct Client *client_p, struct Client *source_p,
731 <          struct Channel *chptr, int parc, int *parn,
776 <          char **parv, int *errors, int alev, int dir, char c, void *d,
777 <          const char *chname)
730 > chm_invex(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
731 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
732   {
733    char *mask = NULL;
734  
781  /* if we have +I disabled, allow local clients to do anything but
782   * set the mode.  This prevents the abuse of +I when just a few
783   * servers support it --fl
784   */
785  if (!ConfigChannel.use_invex && MyClient(source_p) &&
786      (dir == MODE_ADD) && (parc > *parn))
787  {
788    if (*errors & SM_ERR_RPL_I)
789      return;
790    
791    *errors |= SM_ERR_RPL_I;
792    return;
793  }
794
735    if (alev < CHACCESS_HALFOP)
736    {
737      if (!(*errors & SM_ERR_NOOPS))
738 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
739 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
740 <                 me.name, source_p->name, chname);
738 >      sendto_one_numeric(source_p, &me,
739 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
740 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
741      *errors |= SM_ERR_NOOPS;
742      return;
743    }
# Line 814 | Line 754 | chm_invex(struct Client *client_p, struc
754      DLINK_FOREACH(ptr, chptr->invexlist.head)
755      {
756        const struct Ban *banptr = ptr->data;
757 <      sendto_one(client_p, form_str(RPL_INVITELIST), me.name,
758 <                 client_p->name, chname,
759 <                 banptr->name, banptr->username, banptr->host,
760 <                 banptr->who, banptr->when);
757 >
758 >      sendto_one_numeric(source_p, &me, RPL_INVITELIST, chptr->chname,
759 >                         banptr->name, banptr->user, banptr->host,
760 >                         banptr->who, banptr->when);
761      }
762  
763 <    sendto_one(source_p, form_str(RPL_ENDOFINVITELIST), me.name,
824 <               source_p->name, chname);
763 >    sendto_one_numeric(source_p, &me, RPL_ENDOFINVITELIST, chptr->chname);
764      return;
765    }
766  
767    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
768      return;
769  
770 <  mask = parv[(*parn)++];
770 >  mask = nuh_mask[*parn];
771 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
772 >  ++*parn;
773  
774 <  if (IsServer(client_p))
774 >  if (!MyConnect(source_p))
775      if (strchr(mask, ' '))
776        return;
777  
# Line 850 | Line 791 | chm_invex(struct Client *client_p, struc
791  
792    mode_changes[mode_count].letter = c;
793    mode_changes[mode_count].dir = dir;
794 <  mode_changes[mode_count].caps = CAP_IE;
854 <  mode_changes[mode_count].nocaps = 0;
855 <
856 <  if (ConfigChannel.use_invex)
857 <    mode_changes[mode_count].mems = ONLY_CHANOPS;
858 <  else
859 <    mode_changes[mode_count].mems = ONLY_SERVERS;
860 <
794 >  mode_changes[mode_count].mems = ONLY_CHANOPS;
795    mode_changes[mode_count].id = NULL;
796    mode_changes[mode_count++].arg = mask;
797   }
798  
865 /*
866 * inputs       - pointer to channel
867 * output       - none
868 * side effects - clear ban cache
869 */
870 void
871 clear_ban_cache(struct Channel *chptr)
872 {
873  dlink_node *ptr = NULL;
874
875  DLINK_FOREACH(ptr, chptr->locmembers.head)
876  {
877    struct Membership *ms = ptr->data;
878    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
879  }
880 }
881
799   static void
800 < chm_op(struct Client *client_p, struct Client *source_p,
801 <       struct Channel *chptr, int parc, int *parn,
885 <       char **parv, int *errors, int alev, int dir, char c, void *d,
886 <       const char *chname)
800 > chm_voice(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
801 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
802   {
803 <  char *opnick;
889 <  struct Client *targ_p;
803 >  struct Client *target_p;
804    struct Membership *member;
891  int caps = 0;
805  
806 <  if (alev < CHACCESS_CHANOP)
806 >  if (alev < CHACCESS_HALFOP)
807    {
808      if (!(*errors & SM_ERR_NOOPS))
809 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
810 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
811 <                 me.name, source_p->name, chname);
809 >      sendto_one_numeric(source_p, &me,
810 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
811 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
812      *errors |= SM_ERR_NOOPS;
813      return;
814    }
815  
816 <  if ((dir == MODE_QUERY) || (parc <= *parn))
816 >  if (dir == MODE_QUERY || parc <= *parn)
817      return;
818  
819 <  opnick = parv[(*parn)++];
907 <
908 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
909 <    return;
910 <  if (!IsClient(targ_p))
819 >  if ((target_p = find_chasing(source_p, parv[(*parn)++])) == NULL)
820      return;
821  
822 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
822 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
823    {
824      if (!(*errors & SM_ERR_NOTONCHANNEL))
825 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
917 <                 me.name, source_p->name, opnick, chname);
825 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->chname);
826      *errors |= SM_ERR_NOTONCHANNEL;
827      return;
828    }
# Line 923 | Line 831 | chm_op(struct Client *client_p, struct C
831      return;
832  
833    /* no redundant mode changes */
834 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_CHANOP))
834 >  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_VOICE))
835      return;
836 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_CHANOP))
929 <  {
930 < #ifdef HALFOPS
931 <    if (has_member_flags(member, CHFL_HALFOP))
932 <      chm_hop(client_p, source_p, chptr, parc, parn, parv, errors, alev,
933 <              dir, c, d, chname);
934 < #endif
836 >  if (dir == MODE_DEL && !has_member_flags(member, CHFL_VOICE))
837      return;
936  }
937
938 #ifdef HALFOPS
939  if (dir == MODE_ADD && has_member_flags(member, CHFL_HALFOP))
940  {
941    /* promoting from % to @ is visible only to CAP_HOPS servers */
942    mode_changes[mode_count].letter = 'h';
943    mode_changes[mode_count].dir = MODE_DEL;
944    mode_changes[mode_count].caps = caps = CAP_HOPS;
945    mode_changes[mode_count].nocaps = 0;
946    mode_changes[mode_count].mems = ALL_MEMBERS;
947    mode_changes[mode_count].id = NULL;
948    mode_changes[mode_count].arg = targ_p->name;
949    mode_changes[mode_count++].client = targ_p;
950  }
951 #endif
838  
839 <  mode_changes[mode_count].letter = 'o';
839 >  mode_changes[mode_count].letter = 'v';
840    mode_changes[mode_count].dir = dir;
955  mode_changes[mode_count].caps = caps;
956  mode_changes[mode_count].nocaps = 0;
841    mode_changes[mode_count].mems = ALL_MEMBERS;
842 <  mode_changes[mode_count].id = targ_p->id;
843 <  mode_changes[mode_count].arg = targ_p->name;
960 <  mode_changes[mode_count++].client = targ_p;
842 >  mode_changes[mode_count].id = target_p->id;
843 >  mode_changes[mode_count++].arg = target_p->name;
844  
845    if (dir == MODE_ADD)
846 <  {
964 <    AddMemberFlag(member, CHFL_CHANOP);
965 <    DelMemberFlag(member, CHFL_DEOPPED | CHFL_HALFOP);
966 <  }
846 >    AddMemberFlag(member, CHFL_VOICE);
847    else
848 <    DelMemberFlag(member, CHFL_CHANOP);
848 >    DelMemberFlag(member, CHFL_VOICE);
849   }
850  
971 #ifdef HALFOPS
851   static void
852 < chm_hop(struct Client *client_p, struct Client *source_p,
853 <       struct Channel *chptr, int parc, int *parn,
975 <       char **parv, int *errors, int alev, int dir, char c, void *d,
976 <       const char *chname)
852 > chm_hop(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
853 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
854   {
855 <  char *opnick;
979 <  struct Client *targ_p;
855 >  struct Client *target_p;
856    struct Membership *member;
857  
858 <  /* *sigh* - dont allow halfops to set +/-h, they could fully control a
983 <   * channel if there were no ops - it doesnt solve anything.. MODE_PRIVATE
984 <   * when used with MODE_SECRET is paranoid - cant use +p
985 <   *
986 <   * it needs to be optional per channel - but not via +p, that or remove
987 <   * paranoid.. -- fl_
988 <   *
989 <   * +p means paranoid, it is useless for anything else on modern IRC, as
990 <   * list isn't really usable. If you want to have a private channel these
991 <   * days, you set it +s. Halfops can no longer remove simple modes when
992 <   * +p is set (although they can set +p) so it is safe to use this to
993 <   * control whether they can (de)halfop...
994 <   */
995 <  if (alev <
996 <      ((chptr->mode.mode & MODE_PRIVATE) ? CHACCESS_CHANOP : CHACCESS_HALFOP))
858 >  if (alev < CHACCESS_CHANOP)
859    {
860      if (!(*errors & SM_ERR_NOOPS))
861 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
862 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
863 <                 me.name, source_p->name, chname);
861 >      sendto_one_numeric(source_p, &me,
862 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
863 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
864      *errors |= SM_ERR_NOOPS;
865      return;
866    }
867  
868 <  if ((dir == MODE_QUERY) || (parc <= *parn))
868 >  if (dir == MODE_QUERY || parc <= *parn)
869      return;
870  
871 <  opnick = parv[(*parn)++];
1010 <
1011 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
1012 <    return;
1013 <  if (!IsClient(targ_p))
871 >  if ((target_p = find_chasing(source_p, parv[(*parn)++])) == NULL)
872      return;
873  
874 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
874 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
875    {
876      if (!(*errors & SM_ERR_NOTONCHANNEL))
877 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
1020 <                 me.name, source_p->name, opnick, chname);
877 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->chname);
878      *errors |= SM_ERR_NOTONCHANNEL;
879      return;
880    }
# Line 1026 | Line 883 | chm_hop(struct Client *client_p, struct
883      return;
884  
885    /* no redundant mode changes */
886 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_HALFOP | CHFL_CHANOP))
886 >  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_HALFOP))
887      return;
888    if (dir == MODE_DEL && !has_member_flags(member, CHFL_HALFOP))
889      return;
890  
891    mode_changes[mode_count].letter = 'h';
892    mode_changes[mode_count].dir = dir;
1036  mode_changes[mode_count].caps = CAP_HOPS;
1037  mode_changes[mode_count].nocaps = 0;
893    mode_changes[mode_count].mems = ALL_MEMBERS;
894 <  mode_changes[mode_count].id = targ_p->id;
895 <  mode_changes[mode_count].arg = targ_p->name;
1041 <  mode_changes[mode_count++].client = targ_p;
1042 <
1043 <  mode_changes[mode_count].letter = 'o';
1044 <  mode_changes[mode_count].dir = dir;
1045 <  mode_changes[mode_count].caps = 0;
1046 <  mode_changes[mode_count].nocaps = CAP_HOPS;
1047 <  mode_changes[mode_count].mems = ONLY_SERVERS;
1048 <  mode_changes[mode_count].id = targ_p->id;
1049 <  mode_changes[mode_count].arg = targ_p->name;
1050 <  mode_changes[mode_count++].client = targ_p;
894 >  mode_changes[mode_count].id = target_p->id;
895 >  mode_changes[mode_count++].arg = target_p->name;
896  
897    if (dir == MODE_ADD)
1053  {
898      AddMemberFlag(member, CHFL_HALFOP);
1055    DelMemberFlag(member, CHFL_DEOPPED);
1056  }
899    else
900      DelMemberFlag(member, CHFL_HALFOP);
901   }
1060 #endif
902  
903   static void
904 < chm_voice(struct Client *client_p, struct Client *source_p,
905 <          struct Channel *chptr, int parc, int *parn,
1065 <          char **parv, int *errors, int alev, int dir, char c, void *d,
1066 <          const char *chname)
904 > chm_op(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
905 >       char **parv, int *errors, int alev, int dir, char c, unsigned int d)
906   {
907 <  char *opnick;
1069 <  struct Client *targ_p;
907 >  struct Client *target_p;
908    struct Membership *member;
909  
910 <  if (alev < CHACCESS_HALFOP)
910 >  if (alev < CHACCESS_CHANOP)
911    {
912      if (!(*errors & SM_ERR_NOOPS))
913 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
914 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
915 <                 me.name, source_p->name, chname);
913 >      sendto_one_numeric(source_p, &me,
914 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
915 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
916      *errors |= SM_ERR_NOOPS;
917      return;
918    }
919  
920 <  if ((dir == MODE_QUERY) || parc <= *parn)
920 >  if (dir == MODE_QUERY || parc <= *parn)
921      return;
922  
923 <  opnick = parv[(*parn)++];
1086 <
1087 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
1088 <    return;
1089 <  if (!IsClient(targ_p))
923 >  if ((target_p = find_chasing(source_p, parv[(*parn)++])) == NULL)
924      return;
925  
926 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
926 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
927    {
928      if (!(*errors & SM_ERR_NOTONCHANNEL))
929 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
1096 <                 me.name, source_p->name, opnick, chname);
929 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, target_p->name, chptr->chname);
930      *errors |= SM_ERR_NOTONCHANNEL;
931      return;
932    }
# Line 1102 | Line 935 | chm_voice(struct Client *client_p, struc
935      return;
936  
937    /* no redundant mode changes */
938 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_VOICE))
938 >  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_CHANOP))
939      return;
940 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_VOICE))
940 >  if (dir == MODE_DEL && !has_member_flags(member, CHFL_CHANOP))
941      return;
942  
943 <  mode_changes[mode_count].letter = 'v';
943 >  mode_changes[mode_count].letter = 'o';
944    mode_changes[mode_count].dir = dir;
1112  mode_changes[mode_count].caps = 0;
1113  mode_changes[mode_count].nocaps = 0;
945    mode_changes[mode_count].mems = ALL_MEMBERS;
946 <  mode_changes[mode_count].id = targ_p->id;
947 <  mode_changes[mode_count].arg = targ_p->name;
1117 <  mode_changes[mode_count++].client = targ_p;
946 >  mode_changes[mode_count].id = target_p->id;
947 >  mode_changes[mode_count++].arg = target_p->name;
948  
949    if (dir == MODE_ADD)
950 <    AddMemberFlag(member, CHFL_VOICE);
950 >    AddMemberFlag(member, CHFL_CHANOP);
951    else
952 <    DelMemberFlag(member, CHFL_VOICE);
952 >    DelMemberFlag(member, CHFL_CHANOP);
953   }
954  
955   static void
956 < chm_limit(struct Client *client_p, struct Client *source_p,
957 <          struct Channel *chptr, int parc, int *parn,
1128 <          char **parv, int *errors, int alev, int dir, char c, void *d,
1129 <          const char *chname)
956 > chm_limit(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
957 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
958   {
959 <  int i, limit;
1132 <  char *lstr;
959 >  int limit = 0;
960  
961    if (alev < CHACCESS_HALFOP)
962    {
963      if (!(*errors & SM_ERR_NOOPS))
964 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
965 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
966 <                 me.name, source_p->name, chname);
964 >      sendto_one_numeric(source_p, &me,
965 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
966 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
967      *errors |= SM_ERR_NOOPS;
968      return;
969    }
# Line 1144 | Line 971 | chm_limit(struct Client *client_p, struc
971    if (dir == MODE_QUERY)
972      return;
973  
974 <  if ((dir == MODE_ADD) && parc > *parn)
974 >  if (dir == MODE_ADD && parc > *parn)
975    {
976 <    lstr = parv[(*parn)++];
976 >    char *lstr = parv[(*parn)++];
977  
978 <    if ((limit = atoi(lstr)) <= 0)
978 >    if (EmptyString(lstr) || (limit = atoi(lstr)) <= 0)
979        return;
980  
981 <    ircsprintf(lstr, "%d", limit);
981 >    sprintf(lstr, "%d", limit);
982  
983 <    /* if somebody sets MODE #channel +ll 1 2, accept latter --fl */
984 <    for (i = 0; i < mode_count; i++)
1158 <    {
983 >    /* If somebody sets MODE #channel +ll 1 2, accept latter --fl */
984 >    for (unsigned int i = 0; i < mode_count; ++i)
985        if (mode_changes[i].letter == c && mode_changes[i].dir == MODE_ADD)
986          mode_changes[i].letter = 0;
1161    }
987  
988      mode_changes[mode_count].letter = c;
989      mode_changes[mode_count].dir = MODE_ADD;
1165    mode_changes[mode_count].caps = 0;
1166    mode_changes[mode_count].nocaps = 0;
990      mode_changes[mode_count].mems = ALL_MEMBERS;
991      mode_changes[mode_count].id = NULL;
992      mode_changes[mode_count++].arg = lstr;
# Line 1179 | Line 1002 | chm_limit(struct Client *client_p, struc
1002  
1003      mode_changes[mode_count].letter = c;
1004      mode_changes[mode_count].dir = MODE_DEL;
1182    mode_changes[mode_count].caps = 0;
1183    mode_changes[mode_count].nocaps = 0;
1005      mode_changes[mode_count].mems = ALL_MEMBERS;
1006      mode_changes[mode_count].id = NULL;
1007      mode_changes[mode_count++].arg = NULL;
# Line 1188 | Line 1009 | chm_limit(struct Client *client_p, struc
1009   }
1010  
1011   static void
1012 < chm_key(struct Client *client_p, struct Client *source_p,
1013 <        struct Channel *chptr, int parc, int *parn,
1193 <        char **parv, int *errors, int alev, int dir, char c, void *d,
1194 <        const char *chname)
1012 > chm_key(struct Client *source_p, struct Channel *chptr, int parc, int *parn,
1013 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
1014   {
1196  int i;
1197  char *key;
1198
1015    if (alev < CHACCESS_HALFOP)
1016    {
1017      if (!(*errors & SM_ERR_NOOPS))
1018 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
1019 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
1020 <                 me.name, source_p->name, chname);
1018 >      sendto_one_numeric(source_p, &me,
1019 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
1020 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
1021      *errors |= SM_ERR_NOOPS;
1022      return;
1023    }
# Line 1209 | Line 1025 | chm_key(struct Client *client_p, struct
1025    if (dir == MODE_QUERY)
1026      return;
1027  
1028 <  if ((dir == MODE_ADD) && parc > *parn)
1028 >  if (dir == MODE_ADD && parc > *parn)
1029    {
1030 <    key = parv[(*parn)++];
1030 >    char *key = parv[(*parn)++];
1031  
1032      if (MyClient(source_p))
1033        fix_key(key);
1034      else
1035        fix_key_old(key);
1036  
1037 <    if (*key == '\0')
1037 >    if (EmptyString(key))
1038        return;
1039  
1040      assert(key[0] != ' ');
1041      strlcpy(chptr->mode.key, key, sizeof(chptr->mode.key));
1042  
1043 <    /* if somebody does MODE #channel +kk a b, accept latter --fl */
1044 <    for (i = 0; i < mode_count; i++)
1229 <    {
1043 >    /* If somebody does MODE #channel +kk a b, accept latter --fl */
1044 >    for (unsigned int i = 0; i < mode_count; ++i)
1045        if (mode_changes[i].letter == c && mode_changes[i].dir == MODE_ADD)
1046          mode_changes[i].letter = 0;
1232    }
1047  
1048      mode_changes[mode_count].letter = c;
1049      mode_changes[mode_count].dir = MODE_ADD;
1236    mode_changes[mode_count].caps = 0;
1237    mode_changes[mode_count].nocaps = 0;
1050      mode_changes[mode_count].mems = ALL_MEMBERS;
1051      mode_changes[mode_count].id = NULL;
1052      mode_changes[mode_count++].arg = chptr->mode.key;
# Line 1251 | Line 1063 | chm_key(struct Client *client_p, struct
1063  
1064      mode_changes[mode_count].letter = c;
1065      mode_changes[mode_count].dir = MODE_DEL;
1254    mode_changes[mode_count].caps = 0;
1255    mode_changes[mode_count].nocaps = 0;
1066      mode_changes[mode_count].mems = ALL_MEMBERS;
1067      mode_changes[mode_count].id = NULL;
1068      mode_changes[mode_count++].arg = "*";
# Line 1261 | Line 1071 | chm_key(struct Client *client_p, struct
1071  
1072   struct ChannelMode
1073   {
1074 <  void (*func) (struct Client *client_p, struct Client *source_p,
1075 <                struct Channel *chptr, int parc, int *parn, char **parv,
1076 <                int *errors, int alev, int dir, char c, void *d,
1077 <                const char *chname);
1268 <  void *d;
1074 >  void (*func)(struct Client *,
1075 >               struct Channel *, int, int *, char **,
1076 >               int *, int, int, char, unsigned int);
1077 >  unsigned int d;
1078   };
1079  
1080 < /* *INDENT-OFF* */
1272 < static struct ChannelMode ModeTable[255] =
1080 > static struct ChannelMode ModeTable[256] =
1081   {
1082 <  {chm_nosuch, NULL},
1083 <  {chm_nosuch, NULL},                             /* A */
1084 <  {chm_nosuch, NULL},                             /* B */
1085 <  {chm_nosuch, NULL},                             /* C */
1086 <  {chm_nosuch, NULL},                             /* D */
1087 <  {chm_nosuch, NULL},                             /* E */
1088 <  {chm_nosuch, NULL},                             /* F */
1089 <  {chm_nosuch, NULL},                             /* G */
1090 <  {chm_nosuch, NULL},                             /* H */
1091 <  {chm_invex, NULL},                              /* I */
1092 <  {chm_nosuch, NULL},                             /* J */
1093 <  {chm_nosuch, NULL},                             /* K */
1094 <  {chm_nosuch, NULL},                             /* L */
1095 <  {chm_nosuch, NULL},                             /* M */
1096 <  {chm_nosuch, NULL},                             /* N */
1097 <  {chm_nosuch, NULL},                             /* O */
1098 <  {chm_nosuch, NULL},                             /* P */
1099 <  {chm_nosuch, NULL},                             /* Q */
1100 <  {chm_nosuch, NULL},                             /* R */
1101 <  {chm_nosuch, NULL},                             /* S */
1102 <  {chm_nosuch, NULL},                             /* T */
1103 <  {chm_nosuch, NULL},                             /* U */
1104 <  {chm_nosuch, NULL},                             /* V */
1105 <  {chm_nosuch, NULL},                             /* W */
1106 <  {chm_nosuch, NULL},                             /* X */
1107 <  {chm_nosuch, NULL},                             /* Y */
1108 <  {chm_nosuch, NULL},                             /* Z */
1109 <  {chm_nosuch, NULL},
1110 <  {chm_nosuch, NULL},
1111 <  {chm_nosuch, NULL},
1112 <  {chm_nosuch, NULL},
1113 <  {chm_nosuch, NULL},
1114 <  {chm_nosuch, NULL},
1115 <  {chm_nosuch, NULL},                             /* a */
1116 <  {chm_ban, NULL},                                /* b */
1117 <  {chm_nosuch, NULL},                             /* c */
1118 <  {chm_nosuch, NULL},                             /* d */
1119 <  {chm_except, NULL},                             /* e */
1120 <  {chm_nosuch, NULL},                             /* f */
1121 <  {chm_nosuch, NULL},                             /* g */
1122 < #ifdef HALFOPS
1123 <  {chm_hop, NULL},                                /* h */
1124 < #else
1125 <  {chm_nosuch, NULL},                             /* h */
1126 < #endif
1127 <  {chm_simple, (void *) MODE_INVITEONLY},         /* i */
1128 <  {chm_nosuch, NULL},                             /* j */
1129 <  {chm_key, NULL},                                /* k */
1130 <  {chm_limit, NULL},                              /* l */
1131 <  {chm_simple, (void *) MODE_MODERATED},          /* m */
1132 <  {chm_simple, (void *) MODE_NOPRIVMSGS},         /* n */
1133 <  {chm_op, NULL},                                 /* o */
1134 <  {chm_simple, (void *) MODE_PRIVATE},            /* p */
1135 <  {chm_nosuch, NULL},                             /* q */
1136 <  {chm_nosuch, NULL},                             /* r */
1137 <  {chm_simple, (void *) MODE_SECRET},             /* s */
1138 <  {chm_simple, (void *) MODE_TOPICLIMIT},         /* t */
1139 <  {chm_nosuch, NULL},                             /* u */
1140 <  {chm_voice, NULL},                              /* v */
1141 <  {chm_nosuch, NULL},                             /* w */
1142 <  {chm_nosuch, NULL},                             /* x */
1143 <  {chm_nosuch, NULL},                             /* y */
1144 <  {chm_nosuch, NULL},                             /* z */
1082 >  { chm_nosuch,  0 },                   /* 0x00 */
1083 >  { chm_nosuch,  0 },                   /* 0x01 */
1084 >  { chm_nosuch,  0 },                   /* 0x02 */
1085 >  { chm_nosuch,  0 },                   /* 0x03 */
1086 >  { chm_nosuch,  0 },                   /* 0x04 */
1087 >  { chm_nosuch,  0 },                   /* 0x05 */
1088 >  { chm_nosuch,  0 },                   /* 0x06 */
1089 >  { chm_nosuch,  0 },                   /* 0x07 */
1090 >  { chm_nosuch,  0 },                   /* 0x08 */
1091 >  { chm_nosuch,  0 },                   /* 0x09 */
1092 >  { chm_nosuch,  0 },                   /* 0x0a */
1093 >  { chm_nosuch,  0 },                   /* 0x0b */
1094 >  { chm_nosuch,  0 },                   /* 0x0c */
1095 >  { chm_nosuch,  0 },                   /* 0x0d */
1096 >  { chm_nosuch,  0 },                   /* 0x0e */
1097 >  { chm_nosuch,  0 },                   /* 0x0f */
1098 >  { chm_nosuch,  0 },                   /* 0x10 */
1099 >  { chm_nosuch,  0 },                   /* 0x11 */
1100 >  { chm_nosuch,  0 },                   /* 0x12 */
1101 >  { chm_nosuch,  0 },                   /* 0x13 */
1102 >  { chm_nosuch,  0 },                   /* 0x14 */
1103 >  { chm_nosuch,  0 },                   /* 0x15 */
1104 >  { chm_nosuch,  0 },                   /* 0x16 */
1105 >  { chm_nosuch,  0 },                   /* 0x17 */
1106 >  { chm_nosuch,  0 },                   /* 0x18 */
1107 >  { chm_nosuch,  0 },                   /* 0x19 */
1108 >  { chm_nosuch,  0 },                   /* 0x1a */
1109 >  { chm_nosuch,  0 },                   /* 0x1b */
1110 >  { chm_nosuch,  0 },                   /* 0x1c */
1111 >  { chm_nosuch,  0 },                   /* 0x1d */
1112 >  { chm_nosuch,  0 },                   /* 0x1e */
1113 >  { chm_nosuch,  0 },                   /* 0x1f */
1114 >  { chm_nosuch,  0 },                   /* 0x20 */
1115 >  { chm_nosuch,  0 },                   /* 0x21 */
1116 >  { chm_nosuch,  0 },                   /* 0x22 */
1117 >  { chm_nosuch,  0 },                   /* 0x23 */
1118 >  { chm_nosuch,  0 },                   /* 0x24 */
1119 >  { chm_nosuch,  0 },                   /* 0x25 */
1120 >  { chm_nosuch,  0 },                   /* 0x26 */
1121 >  { chm_nosuch,  0 },                   /* 0x27 */
1122 >  { chm_nosuch,  0 },                   /* 0x28 */
1123 >  { chm_nosuch,  0 },                   /* 0x29 */
1124 >  { chm_nosuch,  0 },                   /* 0x2a */
1125 >  { chm_nosuch,  0 },                   /* 0x2b */
1126 >  { chm_nosuch,  0 },                   /* 0x2c */
1127 >  { chm_nosuch,  0 },                   /* 0x2d */
1128 >  { chm_nosuch,  0 },                   /* 0x2e */
1129 >  { chm_nosuch,  0 },                   /* 0x2f */
1130 >  { chm_nosuch,  0 },                   /* 0x30 */
1131 >  { chm_nosuch,  0 },                   /* 0x31 */
1132 >  { chm_nosuch,  0 },                   /* 0x32 */
1133 >  { chm_nosuch,  0 },                   /* 0x33 */
1134 >  { chm_nosuch,  0 },                   /* 0x34 */
1135 >  { chm_nosuch,  0 },                   /* 0x35 */
1136 >  { chm_nosuch,  0 },                   /* 0x36 */
1137 >  { chm_nosuch,  0 },                   /* 0x37 */
1138 >  { chm_nosuch,  0 },                   /* 0x38 */
1139 >  { chm_nosuch,  0 },                   /* 0x39 */
1140 >  { chm_nosuch,  0 },                   /* 0x3a */
1141 >  { chm_nosuch,  0 },                   /* 0x3b */
1142 >  { chm_nosuch,  0 },                   /* 0x3c */
1143 >  { chm_nosuch,  0 },                   /* 0x3d */
1144 >  { chm_nosuch,  0 },                   /* 0x3e */
1145 >  { chm_nosuch,  0 },                   /* 0x3f */
1146 >  { chm_nosuch,  0 },                   /* @ */
1147 >  { chm_nosuch,  0 },                   /* A */
1148 >  { chm_nosuch,  0 },                   /* B */
1149 >  { chm_nosuch,  0 },                   /* C */
1150 >  { chm_nosuch,  0 },                   /* D */
1151 >  { chm_nosuch,  0 },                   /* E */
1152 >  { chm_nosuch,  0 },                   /* F */
1153 >  { chm_nosuch,  0 },                   /* G */
1154 >  { chm_nosuch,  0 },                   /* H */
1155 >  { chm_invex,   0 },                   /* I */
1156 >  { chm_nosuch,  0 },                   /* J */
1157 >  { chm_nosuch,  0 },                   /* K */
1158 >  { chm_nosuch,  0 },                   /* L */
1159 >  { chm_simple, MODE_MODREG},           /* M */
1160 >  { chm_nosuch,  0 },                   /* N */
1161 >  { chm_operonly, MODE_OPERONLY},       /* O */
1162 >  { chm_nosuch,  0 },                   /* P */
1163 >  { chm_nosuch,  0 },                   /* Q */
1164 >  { chm_simple, MODE_REGONLY},          /* R */
1165 >  { chm_simple, MODE_SSLONLY},          /* S */
1166 >  { chm_nosuch,  0 },                   /* T */
1167 >  { chm_nosuch,  0 },                   /* U */
1168 >  { chm_nosuch,  0 },                   /* V */
1169 >  { chm_nosuch,  0 },                   /* W */
1170 >  { chm_nosuch,  0 },                   /* X */
1171 >  { chm_nosuch,  0 },                   /* Y */
1172 >  { chm_nosuch,  0 },                   /* Z */
1173 >  { chm_nosuch,  0 },
1174 >  { chm_nosuch,  0 },
1175 >  { chm_nosuch,  0 },
1176 >  { chm_nosuch,  0 },
1177 >  { chm_nosuch,  0 },
1178 >  { chm_nosuch,  0 },
1179 >  { chm_nosuch,  0 },                   /* a */
1180 >  { chm_ban,     0 },                   /* b */
1181 >  { chm_simple, MODE_NOCTRL},           /* c */
1182 >  { chm_nosuch,  0 },                   /* d */
1183 >  { chm_except,  0 },                   /* e */
1184 >  { chm_nosuch,  0 },                   /* f */
1185 >  { chm_nosuch,  0 },                   /* g */
1186 >  { chm_hop,     0 },                   /* h */
1187 >  { chm_simple,     MODE_INVITEONLY },  /* i */
1188 >  { chm_nosuch,     0               },  /* j */
1189 >  { chm_key,        0               },  /* k */
1190 >  { chm_limit,      0               },  /* l */
1191 >  { chm_simple,     MODE_MODERATED  },  /* m */
1192 >  { chm_simple,     MODE_NOPRIVMSGS },  /* n */
1193 >  { chm_op,         0               },  /* o */
1194 >  { chm_simple,     MODE_PRIVATE    },  /* p */
1195 >  { chm_nosuch,     0               },  /* q */
1196 >  { chm_registered, MODE_REGISTERED },  /* r */
1197 >  { chm_simple,     MODE_SECRET     },  /* s */
1198 >  { chm_simple,     MODE_TOPICLIMIT },  /* t */
1199 >  { chm_nosuch,     0               },  /* u */
1200 >  { chm_voice,      0               },  /* v */
1201 >  { chm_nosuch,     0               },  /* w */
1202 >  { chm_nosuch,     0               },  /* x */
1203 >  { chm_nosuch,     0               },  /* y */
1204 >  { chm_nosuch,     0               },  /* z */
1205 >  { chm_nosuch,  0 },                   /* 0x7b */
1206 >  { chm_nosuch,  0 },                   /* 0x7c */
1207 >  { chm_nosuch,  0 },                   /* 0x7d */
1208 >  { chm_nosuch,  0 },                   /* 0x7e */
1209 >  { chm_nosuch,  0 },                   /* 0x7f */
1210 >  { chm_nosuch,  0 },                   /* 0x80 */
1211 >  { chm_nosuch,  0 },                   /* 0x81 */
1212 >  { chm_nosuch,  0 },                   /* 0x82 */
1213 >  { chm_nosuch,  0 },                   /* 0x83 */
1214 >  { chm_nosuch,  0 },                   /* 0x84 */
1215 >  { chm_nosuch,  0 },                   /* 0x85 */
1216 >  { chm_nosuch,  0 },                   /* 0x86 */
1217 >  { chm_nosuch,  0 },                   /* 0x87 */
1218 >  { chm_nosuch,  0 },                   /* 0x88 */
1219 >  { chm_nosuch,  0 },                   /* 0x89 */
1220 >  { chm_nosuch,  0 },                   /* 0x8a */
1221 >  { chm_nosuch,  0 },                   /* 0x8b */
1222 >  { chm_nosuch,  0 },                   /* 0x8c */
1223 >  { chm_nosuch,  0 },                   /* 0x8d */
1224 >  { chm_nosuch,  0 },                   /* 0x8e */
1225 >  { chm_nosuch,  0 },                   /* 0x8f */
1226 >  { chm_nosuch,  0 },                   /* 0x90 */
1227 >  { chm_nosuch,  0 },                   /* 0x91 */
1228 >  { chm_nosuch,  0 },                   /* 0x92 */
1229 >  { chm_nosuch,  0 },                   /* 0x93 */
1230 >  { chm_nosuch,  0 },                   /* 0x94 */
1231 >  { chm_nosuch,  0 },                   /* 0x95 */
1232 >  { chm_nosuch,  0 },                   /* 0x96 */
1233 >  { chm_nosuch,  0 },                   /* 0x97 */
1234 >  { chm_nosuch,  0 },                   /* 0x98 */
1235 >  { chm_nosuch,  0 },                   /* 0x99 */
1236 >  { chm_nosuch,  0 },                   /* 0x9a */
1237 >  { chm_nosuch,  0 },                   /* 0x9b */
1238 >  { chm_nosuch,  0 },                   /* 0x9c */
1239 >  { chm_nosuch,  0 },                   /* 0x9d */
1240 >  { chm_nosuch,  0 },                   /* 0x9e */
1241 >  { chm_nosuch,  0 },                   /* 0x9f */
1242 >  { chm_nosuch,  0 },                   /* 0xa0 */
1243 >  { chm_nosuch,  0 },                   /* 0xa1 */
1244 >  { chm_nosuch,  0 },                   /* 0xa2 */
1245 >  { chm_nosuch,  0 },                   /* 0xa3 */
1246 >  { chm_nosuch,  0 },                   /* 0xa4 */
1247 >  { chm_nosuch,  0 },                   /* 0xa5 */
1248 >  { chm_nosuch,  0 },                   /* 0xa6 */
1249 >  { chm_nosuch,  0 },                   /* 0xa7 */
1250 >  { chm_nosuch,  0 },                   /* 0xa8 */
1251 >  { chm_nosuch,  0 },                   /* 0xa9 */
1252 >  { chm_nosuch,  0 },                   /* 0xaa */
1253 >  { chm_nosuch,  0 },                   /* 0xab */
1254 >  { chm_nosuch,  0 },                   /* 0xac */
1255 >  { chm_nosuch,  0 },                   /* 0xad */
1256 >  { chm_nosuch,  0 },                   /* 0xae */
1257 >  { chm_nosuch,  0 },                   /* 0xaf */
1258 >  { chm_nosuch,  0 },                   /* 0xb0 */
1259 >  { chm_nosuch,  0 },                   /* 0xb1 */
1260 >  { chm_nosuch,  0 },                   /* 0xb2 */
1261 >  { chm_nosuch,  0 },                   /* 0xb3 */
1262 >  { chm_nosuch,  0 },                   /* 0xb4 */
1263 >  { chm_nosuch,  0 },                   /* 0xb5 */
1264 >  { chm_nosuch,  0 },                   /* 0xb6 */
1265 >  { chm_nosuch,  0 },                   /* 0xb7 */
1266 >  { chm_nosuch,  0 },                   /* 0xb8 */
1267 >  { chm_nosuch,  0 },                   /* 0xb9 */
1268 >  { chm_nosuch,  0 },                   /* 0xba */
1269 >  { chm_nosuch,  0 },                   /* 0xbb */
1270 >  { chm_nosuch,  0 },                   /* 0xbc */
1271 >  { chm_nosuch,  0 },                   /* 0xbd */
1272 >  { chm_nosuch,  0 },                   /* 0xbe */
1273 >  { chm_nosuch,  0 },                   /* 0xbf */
1274 >  { chm_nosuch,  0 },                   /* 0xc0 */
1275 >  { chm_nosuch,  0 },                   /* 0xc1 */
1276 >  { chm_nosuch,  0 },                   /* 0xc2 */
1277 >  { chm_nosuch,  0 },                   /* 0xc3 */
1278 >  { chm_nosuch,  0 },                   /* 0xc4 */
1279 >  { chm_nosuch,  0 },                   /* 0xc5 */
1280 >  { chm_nosuch,  0 },                   /* 0xc6 */
1281 >  { chm_nosuch,  0 },                   /* 0xc7 */
1282 >  { chm_nosuch,  0 },                   /* 0xc8 */
1283 >  { chm_nosuch,  0 },                   /* 0xc9 */
1284 >  { chm_nosuch,  0 },                   /* 0xca */
1285 >  { chm_nosuch,  0 },                   /* 0xcb */
1286 >  { chm_nosuch,  0 },                   /* 0xcc */
1287 >  { chm_nosuch,  0 },                   /* 0xcd */
1288 >  { chm_nosuch,  0 },                   /* 0xce */
1289 >  { chm_nosuch,  0 },                   /* 0xcf */
1290 >  { chm_nosuch,  0 },                   /* 0xd0 */
1291 >  { chm_nosuch,  0 },                   /* 0xd1 */
1292 >  { chm_nosuch,  0 },                   /* 0xd2 */
1293 >  { chm_nosuch,  0 },                   /* 0xd3 */
1294 >  { chm_nosuch,  0 },                   /* 0xd4 */
1295 >  { chm_nosuch,  0 },                   /* 0xd5 */
1296 >  { chm_nosuch,  0 },                   /* 0xd6 */
1297 >  { chm_nosuch,  0 },                   /* 0xd7 */
1298 >  { chm_nosuch,  0 },                   /* 0xd8 */
1299 >  { chm_nosuch,  0 },                   /* 0xd9 */
1300 >  { chm_nosuch,  0 },                   /* 0xda */
1301 >  { chm_nosuch,  0 },                   /* 0xdb */
1302 >  { chm_nosuch,  0 },                   /* 0xdc */
1303 >  { chm_nosuch,  0 },                   /* 0xdd */
1304 >  { chm_nosuch,  0 },                   /* 0xde */
1305 >  { chm_nosuch,  0 },                   /* 0xdf */
1306 >  { chm_nosuch,  0 },                   /* 0xe0 */
1307 >  { chm_nosuch,  0 },                   /* 0xe1 */
1308 >  { chm_nosuch,  0 },                   /* 0xe2 */
1309 >  { chm_nosuch,  0 },                   /* 0xe3 */
1310 >  { chm_nosuch,  0 },                   /* 0xe4 */
1311 >  { chm_nosuch,  0 },                   /* 0xe5 */
1312 >  { chm_nosuch,  0 },                   /* 0xe6 */
1313 >  { chm_nosuch,  0 },                   /* 0xe7 */
1314 >  { chm_nosuch,  0 },                   /* 0xe8 */
1315 >  { chm_nosuch,  0 },                   /* 0xe9 */
1316 >  { chm_nosuch,  0 },                   /* 0xea */
1317 >  { chm_nosuch,  0 },                   /* 0xeb */
1318 >  { chm_nosuch,  0 },                   /* 0xec */
1319 >  { chm_nosuch,  0 },                   /* 0xed */
1320 >  { chm_nosuch,  0 },                   /* 0xee */
1321 >  { chm_nosuch,  0 },                   /* 0xef */
1322 >  { chm_nosuch,  0 },                   /* 0xf0 */
1323 >  { chm_nosuch,  0 },                   /* 0xf1 */
1324 >  { chm_nosuch,  0 },                   /* 0xf2 */
1325 >  { chm_nosuch,  0 },                   /* 0xf3 */
1326 >  { chm_nosuch,  0 },                   /* 0xf4 */
1327 >  { chm_nosuch,  0 },                   /* 0xf5 */
1328 >  { chm_nosuch,  0 },                   /* 0xf6 */
1329 >  { chm_nosuch,  0 },                   /* 0xf7 */
1330 >  { chm_nosuch,  0 },                   /* 0xf8 */
1331 >  { chm_nosuch,  0 },                   /* 0xf9 */
1332 >  { chm_nosuch,  0 },                   /* 0xfa */
1333 >  { chm_nosuch,  0 },                   /* 0xfb */
1334 >  { chm_nosuch,  0 },                   /* 0xfc */
1335 >  { chm_nosuch,  0 },                   /* 0xfd */
1336 >  { chm_nosuch,  0 },                   /* 0xfe */
1337 >  { chm_nosuch,  0 },                   /* 0xff */
1338   };
1338 /* *INDENT-ON* */
1339  
1340   /* get_channel_access()
1341   *
# Line 1346 | Line 1346 | static struct ChannelMode ModeTable[255]
1346   * side effects - NONE
1347   */
1348   static int
1349 < get_channel_access(struct Client *source_p, struct Membership *member)
1349 > get_channel_access(const struct Client *source_p,
1350 >                   const struct Membership *member)
1351   {
1352    /* Let hacked servers in for now... */
1353    if (!MyClient(source_p))
1354      return CHACCESS_CHANOP;
1355  
1356 <  if (member == NULL)
1356 >  if (!member)
1357      return CHACCESS_NOTONCHAN;
1358  
1359 <  /* just to be sure.. */
1359 >  /* Just to be sure.. */
1360    assert(source_p == member->client_p);
1361  
1362    if (has_member_flags(member, CHFL_CHANOP))
1363      return CHACCESS_CHANOP;
1364  
1364 #ifdef HALFOPS
1365    if (has_member_flags(member, CHFL_HALFOP))
1366      return CHACCESS_HALFOP;
1367 #endif
1367  
1368    return CHACCESS_PEON;
1369   }
1370  
1371 < /* void send_cap_mode_changes(struct Client *client_p,
1372 < *                        struct Client *source_p,
1374 < *                        struct Channel *chptr, int cap, int nocap)
1375 < * Input: The client sending(client_p), the source client(source_p),
1371 > /* send_mode_changes_server()
1372 > * Input: the source client(source_p),
1373   *        the channel to send mode changes for(chptr)
1374   * Output: None.
1375 < * Side-effects: Sends the appropriate mode changes to capable servers.
1379 < *
1380 < * send_cap_mode_changes() will loop the server list itself, because
1381 < * at this point in time we have 4 capabs for channels, CAP_IE, CAP_EX,
1382 < * and a server could support any number of these..
1383 < * so we make the modebufs per server, tailoring them to each servers
1384 < * specific demand.  Its not very pretty, but its one of the few realistic
1385 < * ways to handle having this many capabs for channel modes.. --fl_
1375 > * Side-effects: Sends the appropriate mode changes to servers.
1376   *
1387 * Reverted back to my original design, except that we now keep a count
1388 * of the number of servers which each combination as an optimisation, so
1389 * the capabs combinations which are not needed are not worked out. -A1kmm
1377   */
1391 /* rewritten to ensure parabuf < MODEBUFLEN -db */
1392
1378   static void
1379 < send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
1395 <                      struct Channel *chptr, int cap, int nocap)
1379 > send_mode_changes_server(struct Client *source_p, struct Channel *chptr)
1380   {
1381 <  int i, mbl, pbl, arglen, nc, mc;
1382 <  int len;
1399 <  const char *arg = NULL;
1400 <  char *parptr;
1381 >  int mbl = 0, pbl = 0, arglen = 0, nc = 0, mc = 0;
1382 >  int len = 0;
1383    int dir = MODE_QUERY;
1384 <
1385 <  mc = 0;
1404 <  nc = 0;
1405 <  pbl = 0;
1384 >  const char *arg = NULL;
1385 >  char *parptr = NULL;
1386  
1387    parabuf[0] = '\0';
1388    parptr = parabuf;
1389  
1390 <  if ((cap & CAP_TS6) && source_p->id[0] != '\0')
1391 <    mbl = ircsprintf(modebuf, ":%s TMODE %lu %s ", source_p->id,
1412 <                     (unsigned long)chptr->channelts, chptr->chname);
1413 <  else
1414 <    mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->name,
1415 <                     chptr->chname);
1390 >  mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %lu %s ", source_p->id,
1391 >                 (unsigned long)chptr->channelts, chptr->chname);
1392  
1393 <  /* loop the list of - modes we have */
1394 <  for (i = 0; i < mode_count; i++)
1393 >  /* Loop the list of modes we have */
1394 >  for (unsigned i = 0; i < mode_count; ++i)
1395    {
1396 <    /* if they dont support the cap we need, or they do support a cap they
1421 <     * cant have, then dont add it to the modebuf.. that way they wont see
1422 <     * the mode
1423 <     */
1424 <    if ((mode_changes[i].letter == 0) ||
1425 <        ((cap & mode_changes[i].caps) != mode_changes[i].caps)
1426 <        || ((nocap & mode_changes[i].nocaps) != mode_changes[i].nocaps))
1396 >    if (mode_changes[i].letter == 0)
1397        continue;
1398  
1399 <    arg = "";
1430 <
1431 <    if ((cap & CAP_TS6) && mode_changes[i].id)
1399 >    if (mode_changes[i].id)
1400        arg = mode_changes[i].id;
1401 <    if (*arg == '\0')
1401 >    else
1402        arg = mode_changes[i].arg;
1403  
1404 <    /* if we're creeping past the buf size, we need to send it and make
1437 <     * another line for the other modes
1438 <     * XXX - this could give away server topology with uids being
1439 <     * different lengths, but not much we can do, except possibly break
1440 <     * them as if they were the longest of the nick or uid at all times,
1441 <     * which even then won't work as we don't always know the uid -A1kmm.
1442 <     */
1443 <    if (arg != NULL)
1404 >    if (arg)
1405        arglen = strlen(arg);
1406      else
1407        arglen = 0;
1408  
1409 +    /*
1410 +     * If we're creeping past the buf size, we need to send it and make
1411 +     * another line for the other modes
1412 +     */
1413      if ((mc == MAXMODEPARAMS) ||
1414          ((arglen + mbl + pbl + 2) > IRCD_BUFSIZE) ||
1415          (pbl + arglen + BAN_FUDGE) >= MODEBUFLEN)
1416      {
1417 <      if (nc != 0)
1418 <        sendto_server(client_p, source_p, chptr, cap, nocap,
1419 <                      LL_ICHAN | LL_ICLIENT, "%s %s",
1455 <                      modebuf, parabuf);
1417 >      if (nc)
1418 >        sendto_server(source_p, NOCAPS, NOCAPS, "%s %s", modebuf, parabuf);
1419 >
1420        nc = 0;
1421        mc = 0;
1422  
1423 <      if ((cap & CAP_TS6) && source_p->id[0] != '\0')
1424 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->id,
1461 <                         chptr->chname);
1462 <      else
1463 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->name,
1464 <                         chptr->chname);
1423 >      mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %lu %s ", source_p->id,
1424 >                     (unsigned long)chptr->channelts, chptr->chname);
1425  
1426        pbl = 0;
1427        parabuf[0] = '\0';
# Line 1479 | Line 1439 | send_cap_mode_changes(struct Client *cli
1439      modebuf[mbl] = '\0';
1440      nc++;
1441  
1442 <    if (arg != NULL)
1442 >    if (arg)
1443      {
1444 <      len = ircsprintf(parptr, "%s ", arg);
1444 >      len = sprintf(parptr, "%s ", arg);
1445        pbl += len;
1446        parptr += len;
1447        mc++;
# Line 1489 | Line 1449 | send_cap_mode_changes(struct Client *cli
1449    }
1450  
1451    if (pbl && parabuf[pbl - 1] == ' ')
1452 <    parabuf[pbl - 1] = 0;
1452 >    parabuf[pbl - 1] = '\0';
1453  
1454 <  if (nc != 0)
1455 <    sendto_server(client_p, source_p, chptr, cap, nocap,
1496 <                  LL_ICLIENT, "%s %s", modebuf, parabuf);
1454 >  if (nc)
1455 >    sendto_server(source_p, NOCAPS, NOCAPS, "%s %s", modebuf, parabuf);
1456   }
1457  
1458   /* void send_mode_changes(struct Client *client_p,
# Line 1508 | Line 1467 | send_cap_mode_changes(struct Client *cli
1467   */
1468   /* ensure parabuf < MODEBUFLEN -db */
1469   static void
1470 < send_mode_changes(struct Client *client_p, struct Client *source_p,
1512 <                  struct Channel *chptr, char *chname)
1470 > send_mode_changes(struct Client *source_p, struct Channel *chptr)
1471   {
1472 <  int i, mbl, pbl, arglen, nc, mc;
1473 <  int len;
1516 <  const char *arg = NULL;
1517 <  char *parptr;
1472 >  int mbl = 0, pbl = 0, arglen = 0, nc = 0, mc = 0;
1473 >  int len = 0;
1474    int dir = MODE_QUERY;
1475 +  const char *arg = NULL;
1476 +  char *parptr = NULL;
1477  
1478 <  /* bail out if we have nothing to do... */
1478 >  /* Bail out if we have nothing to do... */
1479    if (!mode_count)
1480      return;
1481  
1482    if (IsServer(source_p))
1483 <    mbl = ircsprintf(modebuf, ":%s MODE %s ", (IsHidden(source_p) ||
1484 <                     ConfigServerHide.hide_servers) ?
1485 <                     me.name : source_p->name, chname);
1483 >    mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1484 >                   ConfigServerHide.hide_servers) ?
1485 >                   me.name : source_p->name, chptr->chname);
1486    else
1487 <    mbl = ircsprintf(modebuf, ":%s!%s@%s MODE %s ", source_p->name,
1488 <                     source_p->username, source_p->host, chname);
1531 <
1532 <  mc = 0;
1533 <  nc = 0;
1534 <  pbl = 0;
1487 >    mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1488 >                   source_p->username, source_p->host, chptr->chname);
1489  
1490    parabuf[0] = '\0';
1491    parptr = parabuf;
1492  
1493 <  for (i = 0; i < mode_count; i++)
1493 >  for (unsigned int i = 0; i < mode_count; ++i)
1494    {
1495      if (mode_changes[i].letter == 0 ||
1542        mode_changes[i].mems == NON_CHANOPS ||
1496          mode_changes[i].mems == ONLY_SERVERS)
1497        continue;
1498  
1499      arg = mode_changes[i].arg;
1500 <    if (arg != NULL)
1500 >    if (arg)
1501        arglen = strlen(arg);
1502      else
1503        arglen = 0;
1504  
1505 <    if ((mc == MAXMODEPARAMS)  ||
1505 >    if ((mc == MAXMODEPARAMS)  ||
1506          ((arglen + mbl + pbl + 2) > IRCD_BUFSIZE) ||
1507 <        ((arglen + pbl + BAN_FUDGE) >= MODEBUFLEN))
1507 >        ((arglen + pbl + BAN_FUDGE) >= MODEBUFLEN))
1508      {
1509        if (mbl && modebuf[mbl - 1] == '-')
1510          modebuf[mbl - 1] = '\0';
1511  
1512 <      if (nc != 0)
1513 <        sendto_channel_local(ALL_MEMBERS, NO, chptr, "%s %s", modebuf, parabuf);
1512 >      if (nc)
1513 >        sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
1514  
1515        nc = 0;
1516        mc = 0;
1517  
1518        if (IsServer(source_p))
1519 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", me.name, chname);
1519 >        mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1520 >                       ConfigServerHide.hide_servers) ?
1521 >                       me.name : source_p->name, chptr->chname);
1522        else
1523 <        mbl = ircsprintf(modebuf, ":%s!%s@%s MODE %s ", source_p->name,
1524 <                         source_p->username, source_p->host, chname);
1523 >        mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1524 >                       source_p->username, source_p->host, chptr->chname);
1525  
1526        pbl = 0;
1527        parabuf[0] = '\0';
# Line 1584 | Line 1539 | send_mode_changes(struct Client *client_
1539      modebuf[mbl] = '\0';
1540      nc++;
1541  
1542 <    if (arg != NULL)
1542 >    if (arg)
1543      {
1544 <      len = ircsprintf(parptr, "%s ", arg);
1544 >      len = sprintf(parptr, "%s ", arg);
1545        pbl += len;
1546        parptr += len;
1547        mc++;
# Line 1594 | Line 1549 | send_mode_changes(struct Client *client_
1549    }
1550  
1551    if (pbl && parabuf[pbl - 1] == ' ')
1552 <    parabuf[pbl - 1] = 0;
1552 >    parabuf[pbl - 1] = '\0';
1553  
1554 <  if (nc != 0)
1555 <    sendto_channel_local(ALL_MEMBERS, NO, chptr, "%s %s", modebuf, parabuf);
1554 >  if (nc)
1555 >    sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
1556  
1557 <  nc = 0;
1558 <  mc = 0;
1557 >  send_mode_changes_server(source_p, chptr);
1558 > }
1559  
1560 <  /* Now send to servers... */
1561 <  for (i = 0; i < NCHCAP_COMBOS; i++)
1607 <    if (chcap_combos[i].count != 0)
1608 <      send_cap_mode_changes(client_p, source_p, chptr,
1609 <                            chcap_combos[i].cap_yes,
1610 <                            chcap_combos[i].cap_no);
1611 < }
1612 <
1613 < /* void set_channel_mode(struct Client *client_p, struct Client *source_p,
1614 < *               struct Channel *chptr, int parc, char **parv,
1615 < *               char *chname)
1616 < * Input: The client we received this from, the client this originated
1560 > /*
1561 > * Input: The the client this originated
1562   *        from, the channel, the parameter count starting at the modes,
1563   *        the parameters, the channel name.
1564   * Output: None.
# Line 1622 | Line 1567 | send_mode_changes(struct Client *client_
1567   *               clients.
1568   */
1569   void
1570 < set_channel_mode(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
1571 <                 struct Membership *member, int parc, char *parv[], char *chname)
1570 > set_channel_mode(struct Client *source_p, struct Channel *chptr,
1571 >                 struct Membership *member, int parc, char *parv[])
1572   {
1573    int dir = MODE_ADD;
1574    int parn = 1;
1575 <  int alevel, errors = 0;
1631 <  char *ml = parv[0], c;
1632 <  int table_position;
1575 >  int alevel = 0, errors = 0;
1576  
1577    mode_count = 0;
1578    mode_limit = 0;
# Line 1637 | Line 1580 | set_channel_mode(struct Client *client_p
1580  
1581    alevel = get_channel_access(source_p, member);
1582  
1583 <  for (; (c = *ml) != '\0'; ml++)
1583 >  for (const char *ml = parv[0]; *ml; ++ml)
1584    {
1585 < #if 0
1643 <    if(mode_count > 20)
1644 <      break;
1645 < #endif
1646 <    switch (c)
1585 >    switch (*ml)
1586      {
1587        case '+':
1588          dir = MODE_ADD;
# Line 1655 | Line 1594 | set_channel_mode(struct Client *client_p
1594          dir = MODE_QUERY;
1595          break;
1596        default:
1597 <        if (c < 'A' || c > 'z')
1598 <          table_position = 0;
1599 <        else
1600 <          table_position = c - 'A' + 1;
1601 <        ModeTable[table_position].func(client_p, source_p, chptr,
1663 <                                       parc, &parn,
1664 <                                       parv, &errors, alevel, dir, c,
1665 <                                       ModeTable[table_position].d,
1666 <                                       chname);
1597 >      {
1598 >        struct ChannelMode *tptr = &ModeTable[(unsigned char)*ml];
1599 >
1600 >        tptr->func(source_p, chptr, parc, &parn, parv,
1601 >                   &errors, alevel, dir, *ml, tptr->d);
1602          break;
1603 +      }
1604      }
1605    }
1606  
1607 <  send_mode_changes(client_p, source_p, chptr, chname);
1607 >  send_mode_changes(source_p, chptr);
1608   }

Diff Legend

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