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

Comparing:
ircd-hybrid/src/channel_mode.c (property svn:keywords), Revision 30 by adx, Sun Oct 2 20:03:27 2005 UTC vs.
ircd-hybrid/trunk/src/channel_mode.c (property svn:keywords), Revision 3283 by michael, Tue Apr 8 16:39:50 2014 UTC

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

Diff Legend

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