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

Comparing ircd-hybrid/trunk/src/channel_mode.c (file contents):
Revision 1618 by michael, Tue Oct 30 21:04:38 2012 UTC vs.
Revision 3149 by michael, Fri Mar 14 12:38:27 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"
# Line 27 | Line 29
29   #include "channel.h"
30   #include "channel_mode.h"
31   #include "client.h"
32 < #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"
36   #include "numeric.h"
37 < #include "s_serv.h"             /* captab */
37 < #include "s_user.h"
37 > #include "s_serv.h"
38   #include "send.h"
39 #include "whowas.h"
40 #include "conf.h"             /* ConfigFileEntry, ConfigChannel */
41 #include "event.h"
39   #include "memory.h"
40 < #include "balloc.h"
44 < #include "log.h"
40 > #include "mempool.h"
41   #include "parse.h"
42  
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_registered(struct Client *, struct Client *, struct Channel *,
58                       int, int *, char **, int *, int, int, char, void *,
59                       const char *);
60 static void chm_limit(struct Client *, struct Client *, struct Channel *,
61                      int, int *, char **, int *, int, int, char, void *,
62                      const char *);
63 static void chm_key(struct Client *, struct Client *, struct Channel *,
64                    int, int *, char **, int *, int, int, char, void *,
65                    const char *);
66 static void chm_op(struct Client *, struct Client *, struct Channel *, int,
67                   int *, char **, int *, int, int, char, void *,
68                   const char *);
69 #ifdef HALFOPS
70 static void chm_hop(struct Client *, struct Client *, struct Channel *, int,
71                   int *, char **, int *, int, int, char, void *,
72                   const char *);
73 #endif
74 static void chm_voice(struct Client *, struct Client *, struct Channel *,
75                      int, int *, char **, int *, int, int, char, void *,
76                      const char *);
77 static void chm_ban(struct Client *, struct Client *, struct Channel *, int,
78                    int *, char **, int *, int, int, char, void *,
79                    const char *);
80 static void chm_except(struct Client *, struct Client *, struct Channel *,
81                       int, int *, char **, int *, int, int, char, void *,
82                       const char *);
83 static void chm_invex(struct Client *, struct Client *, struct Channel *,
84                      int, int *, char **, int *, int, int, char, void *,
85                      const char *);
86 static void send_cap_mode_changes(struct Client *, struct Client *,
87                                  struct Channel *, unsigned int, unsigned int);
88 static void send_mode_changes(struct Client *, struct Client *,
89                              struct Channel *, char *);
90
43   /* 10 is a magic number in hybrid 6 NFI where it comes from -db */
44 < #define BAN_FUDGE       10
93 < #define NCHCAPS         (sizeof(channel_capabs)/sizeof(int))
94 < #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  
113 /* XXX check_string is propably not longer required in add_id and del_id */
74   /* check_string()
75   *
76   * inputs       - string to check
# Line 126 | Line 86 | check_string(char *s)
86    char *str = s;
87    static char star[] = "*";
88  
89 <  if (EmptyString(s))
89 >  if (EmptyString(str))
90      return star;
91  
92    for (; *s; ++s)
# Line 138 | 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 = NULL;
115    dlink_node *ban = NULL;
# Line 170 | 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),
174 <                 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  
# Line 193 | Line 152 | add_id(struct Client *client_p, struct C
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 216 | Line 175 | add_id(struct Client *client_p, struct C
175    DLINK_FOREACH(ban, list->head)
176    {
177      ban_p = ban->data;
178 +
179      if (!irccmp(ban_p->name, name) &&
180 <        !irccmp(ban_p->username, user) &&
180 >        !irccmp(ban_p->user, user) &&
181          !irccmp(ban_p->host, host))
222    {
182        return 0;
224    }
183    }
184  
185 <  ban_p = BlockHeapAlloc(ban_heap);
186 <
187 <  DupString(ban_p->name, name);
188 <  DupString(ban_p->username, user);
189 <  DupString(ban_p->host, host);
232 <
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 ! */
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))
# Line 239 | Line 196 | add_id(struct Client *client_p, struct C
196      ban_p->who = MyMalloc(strlen(client_p->name) +
197                            strlen(client_p->username) +
198                            strlen(client_p->host) + 3);
199 <    ircsprintf(ban_p->who, "%s!%s@%s", client_p->name,
200 <               client_p->username, client_p->host);
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(ban_p->who, client_p->name);
205 >    ban_p->who = xstrdup(client_p->name);
206  
207    dlinkAdd(ban_p, &ban_p->node, list);
208  
# Line 258 | 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;
# Line 268 | Line 227 | del_id(struct Channel *chptr, char *bani
227    char host[HOSTLEN + 1];
228    struct split_nuh_item nuh;
229  
230 <  if (banid == NULL)
272 <    return 0;
230 >  assert(banid);
231  
232    nuh.nuhmask  = check_string(banid);
233    nuh.nickptr  = name;
# Line 286 | Line 244 | del_id(struct Channel *chptr, char *bani
244     * Re-assemble a new n!u@h and print it back to banid for sending
245     * the mode to the channel.
246     */
247 <  ircsprintf(banid, "%s!%s@%s", name, user, host);
247 >  sprintf(banid, "%s!%s@%s", name, user, host);
248  
249    switch (type)
250    {
# Line 302 | Line 260 | del_id(struct Channel *chptr, char *bani
260        list = &chptr->invexlist;
261        break;
262      default:
263 <      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
306 <                           "del_id() called with unknown ban type %d!", type);
263 >      assert(0);
264        return 0;
265    }
266  
# Line 312 | Line 269 | del_id(struct Channel *chptr, char *bani
269      banptr = ban->data;
270  
271      if (!irccmp(name, banptr->name) &&
272 <        !irccmp(user, banptr->username) &&
272 >        !irccmp(user, banptr->user) &&
273          !irccmp(host, banptr->host))
274      {
275        remove_ban(banptr, list);
# Line 323 | Line 280 | del_id(struct Channel *chptr, char *bani
280    return 0;
281   }
282  
326 const struct mode_letter chan_modes[] = {
327  { MODE_INVITEONLY, 'i' },
328  { MODE_MODERATED,  'm' },
329  { MODE_NOPRIVMSGS, 'n' },
330  { MODE_PRIVATE,    'p' },
331  { MODE_REGISTERED, 'r' },
332  { MODE_SECRET,     's' },
333  { MODE_TOPICLIMIT, 't' },
334  { MODE_OPERONLY,   'O' },
335  { MODE_REGONLY,    'R' },
336  { MODE_SSLONLY,    'S' },
337  { 0, '\0' }
338 };
339
283   /* channel_modes()
284   *
285   * inputs       - pointer to channel
# Line 365 | Line 308 | channel_modes(struct Channel *chptr, str
308      *mbuf++ = 'l';
309  
310      if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
311 <      pbuf += ircsprintf(pbuf, "%d ", chptr->mode.limit);
311 >      pbuf += sprintf(pbuf, "%d ", chptr->mode.limit);
312    }
313  
314    if (chptr->mode.key[0])
# Line 373 | Line 316 | channel_modes(struct Channel *chptr, str
316      *mbuf++ = 'k';
317  
318      if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
319 <      ircsprintf(pbuf, "%s ", chptr->mode.key);
319 >      sprintf(pbuf, "%s ", chptr->mode.key);
320    }
321  
322    *mbuf = '\0';
323   }
324  
325   /* fix_key()
326 < *
326 > *
327   * inputs       - pointer to key to clean up
328   * output       - pointer to cleaned up key
329   * side effects - input string is modified
# Line 392 | Line 335 | fix_key(char *arg)
335   {
336    unsigned char *s, *t, c;
337  
338 <  for (s = t = (unsigned char *)arg; (c = *s); s++)
338 >  for (s = t = (unsigned char *)arg; (c = *s); ++s)
339    {
340      c &= 0x7f;
341 +
342      if (c != ':' && c > ' ' && c != ',')
343        *t++ = c;
344    }
345  
346    *t = '\0';
347 <  return(arg);
347 >  return arg;
348   }
349  
350   /* fix_key_old()
351 < *
351 > *
352   * inputs       - pointer to key to clean up
353   * output       - pointer to cleaned up key
354 < * side effects - input string is modifed
354 > * side effects - input string is modifed
355   *
356   * Here we attempt to be compatible with older non-hybrid servers.
357   * We can't back down from the ':' issue however.  --Rodder
# Line 417 | Line 361 | fix_key_old(char *arg)
361   {
362    unsigned char *s, *t, c;
363  
364 <  for (s = t = (unsigned char *)arg; (c = *s); s++)
364 >  for (s = t = (unsigned char *)arg; (c = *s); ++s)
365    {
366      c &= 0x7f;
367 <    if ((c != 0x0a) && (c != ':') && (c != 0x0d) && (c != ','))
367 >
368 >    if ((c != 0x0a) && (c != ':') &&
369 >        (c != 0x0d) && (c != ','))
370        *t++ = c;
371    }
372  
373    *t = '\0';
374 <  return(arg);
374 >  return arg;
375   }
376  
377 < /* bitmasks for various error returns that set_channel_mode should only return
378 < * once per call  -orabidoo
379 < */
380 <
435 < #define SM_ERR_NOTS         0x00000001 /* No TS on channel  */
436 < #define SM_ERR_NOOPS        0x00000002 /* No chan ops       */
437 < #define SM_ERR_UNKNOWN      0x00000004
438 < #define SM_ERR_RPL_B        0x00000008
439 < #define SM_ERR_RPL_E        0x00000010
440 < #define SM_ERR_NOTONCHANNEL 0x00000020 /* Not on channel    */
441 < #define SM_ERR_RPL_I        0x00000040
442 < #define SM_ERR_NOTOPER      0x00000080
443 < #define SM_ERR_ONLYSERVER   0x00000100
444 <
445 < /* Now lets do some stuff to keep track of what combinations of
446 < * servers exist...
447 < * Note that the number of combinations doubles each time you add
448 < * something to this list. Each one is only quick if no servers use that
449 < * combination, but if the numbers get too high here MODE will get too
450 < * slow. I suggest if you get more than 7 here, you consider getting rid
451 < * of some and merging or something. If it wasn't for irc+cs we would
452 < * probably not even need to bother about most of these, but unfortunately
453 < * we do. -A1kmm
454 < */
455 <
456 < /* void init_chcap_usage_counts(void)
457 < *
458 < * Inputs       - none
459 < * Output       - none
460 < * Side-effects - Initialises the usage counts to zero. Fills in the
461 < *                chcap_yes and chcap_no combination tables.
377 > /*
378 > * inputs       - pointer to channel
379 > * output       - none
380 > * side effects - clear ban cache
381   */
382   void
383 < init_chcap_usage_counts(void)
383 > clear_ban_cache(struct Channel *chptr)
384   {
385 <  unsigned long m, c, y, n;
467 <
468 <  memset(chcap_combos, 0, sizeof(chcap_combos));
385 >  dlink_node *ptr = NULL;
386  
387 <  /* For every possible combination */
471 <  for (m = 0; m < NCHCAP_COMBOS; m++)
387 >  DLINK_FOREACH(ptr, chptr->members.head)
388    {
389 <    /* Check each capab */
390 <    for (c = y = n = 0; c < NCHCAPS; c++)
391 <    {
392 <      if ((m & (1 << c)) == 0)
477 <        n |= channel_capabs[c];
478 <      else
479 <        y |= channel_capabs[c];
480 <    }
481 <    chcap_combos[m].cap_yes = y;
482 <    chcap_combos[m].cap_no  = n;
389 >    struct Membership *ms = ptr->data;
390 >
391 >    if (MyConnect(ms->client_p))
392 >      ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
393    }
394   }
395  
486 /* void set_chcap_usage_counts(struct Client *serv_p)
487 * Input: serv_p; The client whose capabs to register.
488 * Output: none
489 * Side-effects: Increments the usage counts for the correct capab
490 *               combination.
491 */
396   void
397 < set_chcap_usage_counts(struct Client *serv_p)
397 > clear_ban_cache_client(struct Client *client_p)
398   {
399 <  int n;
399 >  dlink_node *ptr = NULL;
400  
401 <  for (n = 0; n < NCHCAP_COMBOS; n++)
401 >  DLINK_FOREACH(ptr, client_p->channel.head)
402    {
403 <    if (((serv_p->localClient->caps & chcap_combos[n].cap_yes) ==
404 <         chcap_combos[n].cap_yes) &&
501 <        ((serv_p->localClient->caps & chcap_combos[n].cap_no) == 0))
502 <    {
503 <      chcap_combos[n].count++;
504 <      return;
505 <    }
403 >    struct Membership *ms = ptr->data;
404 >    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
405    }
507
508  /* This should be impossible -A1kmm. */
509  assert(0);
406   }
407  
408 < /* void set_chcap_usage_counts(struct Client *serv_p)
409 < *
514 < * Inputs       - serv_p; The client whose capabs to register.
515 < * Output       - none
516 < * Side-effects - Decrements the usage counts for the correct capab
517 < *                combination.
408 > /* bitmasks for various error returns that set_channel_mode should only return
409 > * once per call  -orabidoo
410   */
519 void
520 unset_chcap_usage_counts(struct Client *serv_p)
521 {
522  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... */
419 <      assert(chcap_combos[n].count > 0);
420 <      chcap_combos[n].count--;
533 <      return;
534 <    }
535 <  }
536 <
537 <  /* This should be impossible -A1kmm. */
538 <  assert(0);
539 < }
412 > #define SM_ERR_NOTS         0x00000001 /* No TS on channel  */
413 > #define SM_ERR_NOOPS        0x00000002 /* No chan ops       */
414 > #define SM_ERR_UNKNOWN      0x00000004
415 > #define SM_ERR_RPL_B        0x00000008
416 > #define SM_ERR_RPL_E        0x00000010
417 > #define SM_ERR_NOTONCHANNEL 0x00000020 /* Not on channel    */
418 > #define SM_ERR_RPL_I        0x00000040
419 > #define SM_ERR_NOTOPER      0x00000080
420 > #define SM_ERR_ONLYSERVER   0x00000100
421  
422   /* Mode functions handle mode changes for a particular mode... */
423   static void
424   chm_nosuch(struct Client *client_p, struct Client *source_p,
425             struct Channel *chptr, int parc, int *parn,
426 <           char **parv, int *errors, int alev, int dir, char c, void *d,
546 <           const char *chname)
426 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
427   {
428    if (*errors & SM_ERR_UNKNOWN)
429      return;
430  
431    *errors |= SM_ERR_UNKNOWN;
432 <  sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name,
553 <             source_p->name, c);
432 >  sendto_one_numeric(source_p, &me, ERR_UNKNOWNMODE, c);
433   }
434  
435   static void
436   chm_simple(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
437             int parc, int *parn, char **parv, int *errors, int alev, int dir,
438 <           char c, void *d, const char *chname)
438 >           char c, unsigned int d)
439   {
561  long mode_type;
562
563  mode_type = (long)d;
564
440    if ((alev < CHACCESS_HALFOP) ||
441 <      ((mode_type == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
441 >      ((d == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
442    {
443      if (!(*errors & SM_ERR_NOOPS))
444 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
445 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
446 <                 me.name, source_p->name, chname);
444 >      sendto_one_numeric(source_p, &me,
445 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
446 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
447      *errors |= SM_ERR_NOOPS;
448      return;
449    }
450  
451    /* If have already dealt with this simple mode, ignore it */
452 <  if (simple_modes_mask & mode_type)
452 >  if (simple_modes_mask & d)
453      return;
454  
455 <  simple_modes_mask |= mode_type;
455 >  simple_modes_mask |= d;
456  
457    /* setting + */
458 <  /* Apparently, (though no one has ever told the hybrid group directly)
459 <   * admins don't like redundant mode checking. ok. It would have been nice
460 <   * if you had have told us directly. I've left the original code snippets
461 <   * in place.
462 <   *
463 <   * -Dianora
464 <   */
465 <  if ((dir == MODE_ADD)) /* && !(chptr->mode.mode & mode_type)) */
458 >  /* Apparently, (though no one has ever told the hybrid group directly)
459 >   * admins don't like redundant mode checking. ok. It would have been nice
460 >   * if you had have told us directly. I've left the original code snippets
461 >   * in place.
462 >   *
463 >   * -Dianora
464 >   */
465 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
466    {
467 <    chptr->mode.mode |= mode_type;
467 >    chptr->mode.mode |= d;
468  
469      mode_changes[mode_count].letter = c;
470      mode_changes[mode_count].dir = MODE_ADD;
596    mode_changes[mode_count].caps = 0;
597    mode_changes[mode_count].nocaps = 0;
471      mode_changes[mode_count].id = NULL;
472      mode_changes[mode_count].mems = ALL_MEMBERS;
473      mode_changes[mode_count++].arg = NULL;
474    }
475 <  else if ((dir == MODE_DEL)) /* && (chptr->mode.mode & mode_type)) */
475 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
476    {
477      /* setting - */
478  
479 <    chptr->mode.mode &= ~mode_type;
479 >    chptr->mode.mode &= ~d;
480  
481      mode_changes[mode_count].letter = c;
482      mode_changes[mode_count].dir = MODE_DEL;
610    mode_changes[mode_count].caps = 0;
611    mode_changes[mode_count].nocaps = 0;
483      mode_changes[mode_count].mems = ALL_MEMBERS;
484      mode_changes[mode_count].id = NULL;
485      mode_changes[mode_count++].arg = NULL;
# Line 618 | Line 489 | chm_simple(struct Client *client_p, stru
489   static void
490   chm_registered(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
491             int parc, int *parn, char **parv, int *errors, int alev, int dir,
492 <           char c, void *d, const char *chname)
492 >           char c, unsigned int d)
493   {
623  long mode_type;
624
625  mode_type = (long)d;
626
627
494    if (!IsServer(source_p) && !HasFlag(source_p, FLAGS_SERVICE))
495    {
496      if (!(*errors & SM_ERR_ONLYSERVER))
497 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
498 <                                    ERR_NOTONCHANNEL : ERR_ONLYSERVERSCANCHANGE),
499 <                 me.name, source_p->name, chname);
497 >      sendto_one_numeric(source_p, &me,
498 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
499 >                         ERR_ONLYSERVERSCANCHANGE, chptr->chname);
500      *errors |= SM_ERR_ONLYSERVER;
501      return;
502    }
503  
504    /* If have already dealt with this simple mode, ignore it */
505 <  if (simple_modes_mask & mode_type)
505 >  if (simple_modes_mask & d)
506      return;
507  
508 <  simple_modes_mask |= mode_type;
508 >  simple_modes_mask |= d;
509  
510    /* setting + */
511 <  /* Apparently, (though no one has ever told the hybrid group directly)
512 <   * admins don't like redundant mode checking. ok. It would have been nice
513 <   * if you had have told us directly. I've left the original code snippets
514 <   * in place.
515 <   *
516 <   * -Dianora
511 >  /* Apparently, (though no one has ever told the hybrid group directly)
512 >   * admins don't like redundant mode checking. ok. It would have been nice
513 >   * if you had have told us directly. I've left the original code snippets
514 >   * in place.
515 >   *
516 >   * -Dianora
517     */
518 <  if ((dir == MODE_ADD)) /* && !(chptr->mode.mode & mode_type)) */
518 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
519    {
520 <    chptr->mode.mode |= mode_type;
520 >    chptr->mode.mode |= d;
521  
522      mode_changes[mode_count].letter = c;
523      mode_changes[mode_count].dir = MODE_ADD;
658    mode_changes[mode_count].caps = 0;
659    mode_changes[mode_count].nocaps = 0;
524      mode_changes[mode_count].id = NULL;
525      mode_changes[mode_count].mems = ALL_MEMBERS;
526      mode_changes[mode_count++].arg = NULL;
527    }
528 <  else if ((dir == MODE_DEL)) /* && (chptr->mode.mode & mode_type)) */
528 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
529    {
530      /* setting - */
531  
532 <    chptr->mode.mode &= ~mode_type;
532 >    chptr->mode.mode &= ~d;
533  
534      mode_changes[mode_count].letter = c;
535      mode_changes[mode_count].dir = MODE_DEL;
672    mode_changes[mode_count].caps = 0;
673    mode_changes[mode_count].nocaps = 0;
536      mode_changes[mode_count].mems = ALL_MEMBERS;
537      mode_changes[mode_count].id = NULL;
538      mode_changes[mode_count++].arg = NULL;
# Line 680 | Line 542 | chm_registered(struct Client *client_p,
542   static void
543   chm_operonly(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
544              int parc, int *parn, char **parv, int *errors, int alev, int dir,
545 <            char c, void *d, const char *chname)
545 >            char c, unsigned int d)
546   {
685  long mode_type;
686
687  mode_type = (long)d;
688
547    if ((alev < CHACCESS_HALFOP) ||
548 <      ((mode_type == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
548 >      ((d == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
549    {
550      if (!(*errors & SM_ERR_NOOPS))
551 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
552 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
553 <                 me.name, source_p->name, chname);
551 >      sendto_one_numeric(source_p, &me,
552 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
553 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
554      *errors |= SM_ERR_NOOPS;
555      return;
556    }
# Line 701 | Line 559 | chm_operonly(struct Client *client_p, st
559      if (!(*errors & SM_ERR_NOTOPER))
560      {
561        if (alev == CHACCESS_NOTONCHAN)
562 <        sendto_one(source_p, form_str(ERR_NOTONCHANNEL),
705 <                   me.name, source_p->name, chname);
562 >        sendto_one_numeric(source_p, &me, ERR_NOTONCHANNEL, chptr->chname);
563        else
564 <        sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
708 <                   me.name, source_p->name);
564 >        sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
565      }
566  
567      *errors |= SM_ERR_NOTOPER;
# Line 713 | Line 569 | chm_operonly(struct Client *client_p, st
569    }
570  
571    /* If have already dealt with this simple mode, ignore it */
572 <  if (simple_modes_mask & mode_type)
572 >  if (simple_modes_mask & d)
573      return;
574  
575 <  simple_modes_mask |= mode_type;
575 >  simple_modes_mask |= d;
576  
577 <  if ((dir == MODE_ADD)) /* && !(chptr->mode.mode & mode_type)) */
577 >  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
578    {
579 <    chptr->mode.mode |= mode_type;
579 >    chptr->mode.mode |= d;
580  
581      mode_changes[mode_count].letter = c;
582      mode_changes[mode_count].dir = MODE_ADD;
727    mode_changes[mode_count].caps = 0;
728    mode_changes[mode_count].nocaps = 0;
583      mode_changes[mode_count].id = NULL;
584      mode_changes[mode_count].mems = ALL_MEMBERS;
585      mode_changes[mode_count].mems = ALL_MEMBERS;
586      mode_changes[mode_count++].arg = NULL;
587    }
588 <  else if ((dir == MODE_DEL)) /* && (chptr->mode.mode & mode_type)) */
588 >  else if (dir == MODE_DEL) /* && (chptr->mode.mode & d)) */
589    {
590      /* setting - */
591  
592 <    chptr->mode.mode &= ~mode_type;
592 >    chptr->mode.mode &= ~d;
593  
594      mode_changes[mode_count].letter = c;
595      mode_changes[mode_count].dir = MODE_DEL;
742    mode_changes[mode_count].caps = 0;
743    mode_changes[mode_count].nocaps = 0;
596      mode_changes[mode_count].mems = ALL_MEMBERS;
597      mode_changes[mode_count].id = NULL;
598      mode_changes[mode_count++].arg = NULL;
# Line 750 | Line 602 | chm_operonly(struct Client *client_p, st
602   static void
603   chm_ban(struct Client *client_p, struct Client *source_p,
604          struct Channel *chptr, int parc, int *parn,
605 <        char **parv, int *errors, int alev, int dir, char c, void *d,
754 <        const char *chname)
605 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
606   {
607    char *mask = NULL;
608  
# Line 767 | Line 618 | chm_ban(struct Client *client_p, struct
618      DLINK_FOREACH(ptr, chptr->banlist.head)
619      {
620        const struct Ban *banptr = ptr->data;
621 <      sendto_one(client_p, form_str(RPL_BANLIST),
622 <                 me.name, client_p->name, chname,
623 <                 banptr->name, banptr->username, banptr->host,
773 <                 banptr->who, banptr->when);
621 >      sendto_one_numeric(source_p, &me, RPL_BANLIST, chptr->chname,
622 >                         banptr->name, banptr->user, banptr->host,
623 >                         banptr->who, banptr->when);
624      }
625  
626 <    sendto_one(source_p, form_str(RPL_ENDOFBANLIST), me.name,
777 <               source_p->name, chname);
626 >    sendto_one_numeric(source_p, &me, RPL_ENDOFBANLIST, chptr->chname);
627      return;
628    }
629  
630    if (alev < CHACCESS_HALFOP)
631    {
632      if (!(*errors & SM_ERR_NOOPS))
633 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
634 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
635 <                 me.name, source_p->name, chname);
633 >      sendto_one_numeric(source_p, &me,
634 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
635 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
636      *errors |= SM_ERR_NOOPS;
637      return;
638    }
# Line 815 | Line 664 | chm_ban(struct Client *client_p, struct
664  
665    mode_changes[mode_count].letter = c;
666    mode_changes[mode_count].dir = dir;
818  mode_changes[mode_count].caps = 0;
819  mode_changes[mode_count].nocaps = 0;
667    mode_changes[mode_count].mems = ALL_MEMBERS;
668    mode_changes[mode_count].id = NULL;
669    mode_changes[mode_count++].arg = mask;
# Line 825 | Line 672 | chm_ban(struct Client *client_p, struct
672   static void
673   chm_except(struct Client *client_p, struct Client *source_p,
674             struct Channel *chptr, int parc, int *parn,
675 <           char **parv, int *errors, int alev, int dir, char c, void *d,
829 <           const char *chname)
675 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
676   {
677    char *mask = NULL;
678  
679    if (alev < CHACCESS_HALFOP)
680    {
681      if (!(*errors & SM_ERR_NOOPS))
682 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
683 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
684 <                 me.name, source_p->name, chname);
682 >      sendto_one_numeric(source_p, &me,
683 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
684 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
685      *errors |= SM_ERR_NOOPS;
686      return;
687    }
# Line 852 | Line 698 | chm_except(struct Client *client_p, stru
698      DLINK_FOREACH(ptr, chptr->exceptlist.head)
699      {
700        const struct Ban *banptr = ptr->data;
701 <      sendto_one(client_p, form_str(RPL_EXCEPTLIST),
702 <                 me.name, client_p->name, chname,
703 <                 banptr->name, banptr->username, banptr->host,
704 <                 banptr->who, banptr->when);
701 >
702 >      sendto_one_numeric(source_p, &me, RPL_EXCEPTLIST, chptr->chname,
703 >                         banptr->name, banptr->user, banptr->host,
704 >                         banptr->who, banptr->when);
705      }
706  
707 <    sendto_one(source_p, form_str(RPL_ENDOFEXCEPTLIST), me.name,
862 <               source_p->name, chname);
707 >    sendto_one_numeric(source_p, &me, RPL_ENDOFEXCEPTLIST, chptr->chname);
708      return;
709    }
710  
# Line 890 | Line 735 | chm_except(struct Client *client_p, stru
735  
736    mode_changes[mode_count].letter = c;
737    mode_changes[mode_count].dir = dir;
893  mode_changes[mode_count].caps = CAP_EX;
894  mode_changes[mode_count].nocaps = 0;
738    mode_changes[mode_count].mems = ONLY_CHANOPS;
739    mode_changes[mode_count].id = NULL;
740    mode_changes[mode_count++].arg = mask;
# Line 900 | Line 743 | chm_except(struct Client *client_p, stru
743   static void
744   chm_invex(struct Client *client_p, struct Client *source_p,
745            struct Channel *chptr, int parc, int *parn,
746 <          char **parv, int *errors, int alev, int dir, char c, void *d,
904 <          const char *chname)
746 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
747   {
748    char *mask = NULL;
749  
750    if (alev < CHACCESS_HALFOP)
751    {
752      if (!(*errors & SM_ERR_NOOPS))
753 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
754 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
755 <                 me.name, source_p->name, chname);
753 >      sendto_one_numeric(source_p, &me,
754 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
755 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
756      *errors |= SM_ERR_NOOPS;
757      return;
758    }
# Line 927 | Line 769 | chm_invex(struct Client *client_p, struc
769      DLINK_FOREACH(ptr, chptr->invexlist.head)
770      {
771        const struct Ban *banptr = ptr->data;
772 <      sendto_one(client_p, form_str(RPL_INVITELIST), me.name,
773 <                 client_p->name, chname,
774 <                 banptr->name, banptr->username, banptr->host,
775 <                 banptr->who, banptr->when);
772 >
773 >      sendto_one_numeric(source_p, &me, RPL_INVITELIST, chptr->chname,
774 >                         banptr->name, banptr->user, banptr->host,
775 >                         banptr->who, banptr->when);
776      }
777  
778 <    sendto_one(source_p, form_str(RPL_ENDOFINVITELIST), me.name,
937 <               source_p->name, chname);
778 >    sendto_one_numeric(source_p, &me, RPL_ENDOFINVITELIST, chptr->chname);
779      return;
780    }
781  
# Line 965 | Line 806 | chm_invex(struct Client *client_p, struc
806  
807    mode_changes[mode_count].letter = c;
808    mode_changes[mode_count].dir = dir;
968  mode_changes[mode_count].caps = CAP_IE;
969  mode_changes[mode_count].nocaps = 0;
809    mode_changes[mode_count].mems = ONLY_CHANOPS;
810    mode_changes[mode_count].id = NULL;
811    mode_changes[mode_count++].arg = mask;
812   }
813  
975 /*
976 * inputs       - pointer to channel
977 * output       - none
978 * side effects - clear ban cache
979 */
980 void
981 clear_ban_cache(struct Channel *chptr)
982 {
983  dlink_node *ptr = NULL;
984
985  DLINK_FOREACH(ptr, chptr->members.head)
986  {
987    struct Membership *ms = ptr->data;
988
989    if (MyConnect(ms->client_p))
990      ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
991  }
992 }
993
994 void
995 clear_ban_cache_client(struct Client *client_p)
996 {
997  dlink_node *ptr = NULL;
998
999  DLINK_FOREACH(ptr, client_p->channel.head)
1000  {
1001    struct Membership *ms = ptr->data;
1002    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
1003  }
1004 }
1005
814   static void
815 < chm_op(struct Client *client_p, struct Client *source_p,
816 <       struct Channel *chptr, int parc, int *parn,
817 <       char **parv, int *errors, int alev, int dir, char c, void *d,
1010 <       const char *chname)
815 > chm_voice(struct Client *client_p, struct Client *source_p,
816 >          struct Channel *chptr, int parc, int *parn,
817 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
818   {
819 <  char *opnick;
820 <  struct Client *targ_p;
819 >  const char *opnick = NULL;
820 >  struct Client *target_p;
821    struct Membership *member;
1015  int caps = 0;
822  
823 <  if (alev < CHACCESS_CHANOP)
823 >  if (alev < CHACCESS_HALFOP)
824    {
825      if (!(*errors & SM_ERR_NOOPS))
826 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
827 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
828 <                 me.name, source_p->name, chname);
826 >      sendto_one_numeric(source_p, &me,
827 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
828 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
829      *errors |= SM_ERR_NOOPS;
830      return;
831    }
832  
833 <  if ((dir == MODE_QUERY) || (parc <= *parn))
833 >  if ((dir == MODE_QUERY) || parc <= *parn)
834      return;
835  
836    opnick = parv[(*parn)++];
837  
838 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
838 >  if ((target_p = find_chasing(source_p, opnick, NULL)) == NULL)
839      return;
840 <  if (!IsClient(targ_p))
840 >  if (!IsClient(target_p))
841      return;
842  
843 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
843 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
844    {
845      if (!(*errors & SM_ERR_NOTONCHANNEL))
846 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
1041 <                 me.name, source_p->name, opnick, chname);
846 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, opnick, chptr->chname);
847      *errors |= SM_ERR_NOTONCHANNEL;
848      return;
849    }
# Line 1047 | Line 852 | chm_op(struct Client *client_p, struct C
852      return;
853  
854    /* no redundant mode changes */
855 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_CHANOP))
855 >  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_VOICE))
856      return;
857 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_CHANOP))
1053 <  {
1054 < #ifdef HALFOPS
1055 <    if (has_member_flags(member, CHFL_HALFOP))
1056 <    {
1057 <      --*parn;
1058 <      chm_hop(client_p, source_p, chptr, parc, parn, parv, errors, alev,
1059 <              dir, c, d, chname);
1060 <    }
1061 < #endif
857 >  if (dir == MODE_DEL && !has_member_flags(member, CHFL_VOICE))
858      return;
1063  }
1064
1065 #ifdef HALFOPS
1066  if (dir == MODE_ADD && has_member_flags(member, CHFL_HALFOP))
1067  {
1068    /* promoting from % to @ is visible only to CAP_HOPS servers */
1069    mode_changes[mode_count].letter = 'h';
1070    mode_changes[mode_count].dir = MODE_DEL;
1071    mode_changes[mode_count].caps = caps = CAP_HOPS;
1072    mode_changes[mode_count].nocaps = 0;
1073    mode_changes[mode_count].mems = ALL_MEMBERS;
1074    mode_changes[mode_count].id = NULL;
1075    mode_changes[mode_count].arg = targ_p->name;
1076    mode_changes[mode_count++].client = targ_p;
1077  }
1078 #endif
859  
860 <  mode_changes[mode_count].letter = 'o';
860 >  mode_changes[mode_count].letter = 'v';
861    mode_changes[mode_count].dir = dir;
1082  mode_changes[mode_count].caps = caps;
1083  mode_changes[mode_count].nocaps = 0;
862    mode_changes[mode_count].mems = ALL_MEMBERS;
863 <  mode_changes[mode_count].id = targ_p->id;
864 <  mode_changes[mode_count].arg = targ_p->name;
865 <  mode_changes[mode_count++].client = targ_p;
863 >  mode_changes[mode_count].id = target_p->id;
864 >  mode_changes[mode_count].arg = target_p->name;
865 >  mode_changes[mode_count++].client = target_p;
866  
867    if (dir == MODE_ADD)
868 <  {
1091 <    AddMemberFlag(member, CHFL_CHANOP);
1092 <    DelMemberFlag(member, CHFL_DEOPPED | CHFL_HALFOP);
1093 <  }
868 >    AddMemberFlag(member, CHFL_VOICE);
869    else
870 <    DelMemberFlag(member, CHFL_CHANOP);
870 >    DelMemberFlag(member, CHFL_VOICE);
871   }
872  
873   #ifdef HALFOPS
874   static void
875   chm_hop(struct Client *client_p, struct Client *source_p,
876         struct Channel *chptr, int parc, int *parn,
877 <       char **parv, int *errors, int alev, int dir, char c, void *d,
1103 <       const char *chname)
877 >       char **parv, int *errors, int alev, int dir, char c, unsigned int d)
878   {
879 <  char *opnick;
880 <  struct Client *targ_p;
879 >  const char *opnick = NULL;
880 >  struct Client *target_p;
881    struct Membership *member;
882  
883    /* *sigh* - dont allow halfops to set +/-h, they could fully control a
# Line 1123 | Line 897 | chm_hop(struct Client *client_p, struct
897        ((chptr->mode.mode & MODE_PRIVATE) ? CHACCESS_CHANOP : CHACCESS_HALFOP))
898    {
899      if (!(*errors & SM_ERR_NOOPS))
900 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
901 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
902 <                 me.name, source_p->name, chname);
900 >      sendto_one_numeric(source_p, &me,
901 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
902 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
903      *errors |= SM_ERR_NOOPS;
904      return;
905    }
# Line 1135 | Line 909 | chm_hop(struct Client *client_p, struct
909  
910    opnick = parv[(*parn)++];
911  
912 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
912 >  if ((target_p = find_chasing(source_p, opnick, NULL)) == NULL)
913      return;
914 <  if (!IsClient(targ_p))
914 >  if (!IsClient(target_p))
915      return;
916  
917 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
917 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
918    {
919      if (!(*errors & SM_ERR_NOTONCHANNEL))
920 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
1147 <                 me.name, source_p->name, opnick, chname);
920 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, opnick, chptr->chname);
921      *errors |= SM_ERR_NOTONCHANNEL;
922      return;
923    }
# Line 1153 | Line 926 | chm_hop(struct Client *client_p, struct
926      return;
927  
928    /* no redundant mode changes */
929 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_HALFOP | CHFL_CHANOP))
929 >  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_HALFOP))
930      return;
931    if (dir == MODE_DEL && !has_member_flags(member, CHFL_HALFOP))
932      return;
933  
934    mode_changes[mode_count].letter = 'h';
935    mode_changes[mode_count].dir = dir;
1163  mode_changes[mode_count].caps = CAP_HOPS;
1164  mode_changes[mode_count].nocaps = 0;
936    mode_changes[mode_count].mems = ALL_MEMBERS;
937 <  mode_changes[mode_count].id = targ_p->id;
938 <  mode_changes[mode_count].arg = targ_p->name;
939 <  mode_changes[mode_count++].client = targ_p;
1169 <
1170 <  mode_changes[mode_count].letter = 'o';
1171 <  mode_changes[mode_count].dir = dir;
1172 <  mode_changes[mode_count].caps = 0;
1173 <  mode_changes[mode_count].nocaps = CAP_HOPS;
1174 <  mode_changes[mode_count].mems = ONLY_SERVERS;
1175 <  mode_changes[mode_count].id = targ_p->id;
1176 <  mode_changes[mode_count].arg = targ_p->name;
1177 <  mode_changes[mode_count++].client = targ_p;
937 >  mode_changes[mode_count].id = target_p->id;
938 >  mode_changes[mode_count].arg = target_p->name;
939 >  mode_changes[mode_count++].client = target_p;
940  
941    if (dir == MODE_ADD)
942    {
# Line 1187 | Line 949 | chm_hop(struct Client *client_p, struct
949   #endif
950  
951   static void
952 < chm_voice(struct Client *client_p, struct Client *source_p,
953 <          struct Channel *chptr, int parc, int *parn,
954 <          char **parv, int *errors, int alev, int dir, char c, void *d,
1193 <          const char *chname)
952 > chm_op(struct Client *client_p, struct Client *source_p,
953 >       struct Channel *chptr, int parc, int *parn,
954 >       char **parv, int *errors, int alev, int dir, char c, unsigned int d)
955   {
956 <  char *opnick;
957 <  struct Client *targ_p;
956 >  const char *opnick = NULL;
957 >  struct Client *target_p;
958    struct Membership *member;
959  
960 <  if (alev < CHACCESS_HALFOP)
960 >  if (alev < CHACCESS_CHANOP)
961    {
962      if (!(*errors & SM_ERR_NOOPS))
963 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
964 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
965 <                 me.name, source_p->name, chname);
963 >      sendto_one_numeric(source_p, &me,
964 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
965 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
966      *errors |= SM_ERR_NOOPS;
967      return;
968    }
969  
970 <  if ((dir == MODE_QUERY) || parc <= *parn)
970 >  if ((dir == MODE_QUERY) || (parc <= *parn))
971      return;
972  
973    opnick = parv[(*parn)++];
974  
975 <  if ((targ_p = find_chasing(client_p, source_p, opnick, NULL)) == NULL)
975 >  if ((target_p = find_chasing(source_p, opnick, NULL)) == NULL)
976      return;
977 <  if (!IsClient(targ_p))
977 >  if (!IsClient(target_p))
978      return;
979  
980 <  if ((member = find_channel_link(targ_p, chptr)) == NULL)
980 >  if ((member = find_channel_link(target_p, chptr)) == NULL)
981    {
982      if (!(*errors & SM_ERR_NOTONCHANNEL))
983 <      sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
1223 <                 me.name, source_p->name, opnick, chname);
983 >      sendto_one_numeric(source_p, &me, ERR_USERNOTINCHANNEL, opnick, chptr->chname);
984      *errors |= SM_ERR_NOTONCHANNEL;
985      return;
986    }
# Line 1229 | Line 989 | chm_voice(struct Client *client_p, struc
989      return;
990  
991    /* no redundant mode changes */
992 <  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_VOICE))
992 >  if (dir == MODE_ADD &&  has_member_flags(member, CHFL_CHANOP))
993      return;
994 <  if (dir == MODE_DEL && !has_member_flags(member, CHFL_VOICE))
994 >  if (dir == MODE_DEL && !has_member_flags(member, CHFL_CHANOP))
995      return;
996  
997 <  mode_changes[mode_count].letter = 'v';
997 >  mode_changes[mode_count].letter = 'o';
998    mode_changes[mode_count].dir = dir;
1239  mode_changes[mode_count].caps = 0;
1240  mode_changes[mode_count].nocaps = 0;
999    mode_changes[mode_count].mems = ALL_MEMBERS;
1000 <  mode_changes[mode_count].id = targ_p->id;
1001 <  mode_changes[mode_count].arg = targ_p->name;
1002 <  mode_changes[mode_count++].client = targ_p;
1000 >  mode_changes[mode_count].id = target_p->id;
1001 >  mode_changes[mode_count].arg = target_p->name;
1002 >  mode_changes[mode_count++].client = target_p;
1003  
1004    if (dir == MODE_ADD)
1005 <    AddMemberFlag(member, CHFL_VOICE);
1005 >  {
1006 >    AddMemberFlag(member, CHFL_CHANOP);
1007 >    DelMemberFlag(member, CHFL_DEOPPED);
1008 >  }
1009    else
1010 <    DelMemberFlag(member, CHFL_VOICE);
1010 >    DelMemberFlag(member, CHFL_CHANOP);
1011   }
1012  
1013   static void
1014   chm_limit(struct Client *client_p, struct Client *source_p,
1015            struct Channel *chptr, int parc, int *parn,
1016 <          char **parv, int *errors, int alev, int dir, char c, void *d,
1256 <          const char *chname)
1016 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
1017   {
1018 <  int i, limit;
1018 >  unsigned int i;
1019 >  int limit;
1020    char *lstr;
1021  
1022    if (alev < CHACCESS_HALFOP)
1023    {
1024      if (!(*errors & SM_ERR_NOOPS))
1025 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
1026 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
1027 <                 me.name, source_p->name, chname);
1025 >      sendto_one_numeric(source_p, &me,
1026 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
1027 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
1028      *errors |= SM_ERR_NOOPS;
1029      return;
1030    }
# Line 1278 | Line 1039 | chm_limit(struct Client *client_p, struc
1039      if ((limit = atoi(lstr)) <= 0)
1040        return;
1041  
1042 <    ircsprintf(lstr, "%d", limit);
1042 >    sprintf(lstr, "%d", limit);
1043  
1044      /* if somebody sets MODE #channel +ll 1 2, accept latter --fl */
1045      for (i = 0; i < mode_count; i++)
1285    {
1046        if (mode_changes[i].letter == c && mode_changes[i].dir == MODE_ADD)
1047          mode_changes[i].letter = 0;
1288    }
1048  
1049      mode_changes[mode_count].letter = c;
1050      mode_changes[mode_count].dir = MODE_ADD;
1292    mode_changes[mode_count].caps = 0;
1293    mode_changes[mode_count].nocaps = 0;
1051      mode_changes[mode_count].mems = ALL_MEMBERS;
1052      mode_changes[mode_count].id = NULL;
1053      mode_changes[mode_count++].arg = lstr;
# Line 1306 | Line 1063 | chm_limit(struct Client *client_p, struc
1063  
1064      mode_changes[mode_count].letter = c;
1065      mode_changes[mode_count].dir = MODE_DEL;
1309    mode_changes[mode_count].caps = 0;
1310    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 = NULL;
# Line 1317 | Line 1072 | chm_limit(struct Client *client_p, struc
1072   static void
1073   chm_key(struct Client *client_p, struct Client *source_p,
1074          struct Channel *chptr, int parc, int *parn,
1075 <        char **parv, int *errors, int alev, int dir, char c, void *d,
1321 <        const char *chname)
1075 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
1076   {
1077 <  int i;
1077 >  unsigned int i;
1078    char *key;
1079  
1080    if (alev < CHACCESS_HALFOP)
1081    {
1082      if (!(*errors & SM_ERR_NOOPS))
1083 <      sendto_one(source_p, form_str(alev == CHACCESS_NOTONCHAN ?
1084 <                                    ERR_NOTONCHANNEL : ERR_CHANOPRIVSNEEDED),
1085 <                 me.name, source_p->name, chname);
1083 >      sendto_one_numeric(source_p, &me,
1084 >                         alev == CHACCESS_NOTONCHAN ? ERR_NOTONCHANNEL :
1085 >                         ERR_CHANOPRIVSNEEDED, chptr->chname);
1086      *errors |= SM_ERR_NOOPS;
1087      return;
1088    }
# Line 1353 | Line 1107 | chm_key(struct Client *client_p, struct
1107  
1108      /* if somebody does MODE #channel +kk a b, accept latter --fl */
1109      for (i = 0; i < mode_count; i++)
1356    {
1110        if (mode_changes[i].letter == c && mode_changes[i].dir == MODE_ADD)
1111          mode_changes[i].letter = 0;
1359    }
1112  
1113      mode_changes[mode_count].letter = c;
1114      mode_changes[mode_count].dir = MODE_ADD;
1363    mode_changes[mode_count].caps = 0;
1364    mode_changes[mode_count].nocaps = 0;
1115      mode_changes[mode_count].mems = ALL_MEMBERS;
1116      mode_changes[mode_count].id = NULL;
1117      mode_changes[mode_count++].arg = chptr->mode.key;
# Line 1378 | Line 1128 | chm_key(struct Client *client_p, struct
1128  
1129      mode_changes[mode_count].letter = c;
1130      mode_changes[mode_count].dir = MODE_DEL;
1381    mode_changes[mode_count].caps = 0;
1382    mode_changes[mode_count].nocaps = 0;
1131      mode_changes[mode_count].mems = ALL_MEMBERS;
1132      mode_changes[mode_count].id = NULL;
1133      mode_changes[mode_count++].arg = "*";
# Line 1388 | Line 1136 | chm_key(struct Client *client_p, struct
1136  
1137   struct ChannelMode
1138   {
1139 <  void (*func) (struct Client *client_p, struct Client *source_p,
1140 <                struct Channel *chptr, int parc, int *parn, char **parv,
1141 <                int *errors, int alev, int dir, char c, void *d,
1142 <                const char *chname);
1395 <  void *d;
1139 >  void (*func)(struct Client *, struct Client *,
1140 >               struct Channel *, int, int *, char **,
1141 >               int *, int, int, char, unsigned int);
1142 >  unsigned int d;
1143   };
1144  
1145 < static struct ChannelMode ModeTable[255] =
1145 > static struct ChannelMode ModeTable[256] =
1146   {
1147 <  {chm_nosuch, NULL},
1148 <  {chm_nosuch, NULL},                             /* A */
1149 <  {chm_nosuch, NULL},                             /* B */
1150 <  {chm_nosuch, NULL},                             /* C */
1151 <  {chm_nosuch, NULL},                             /* D */
1152 <  {chm_nosuch, NULL},                             /* E */
1153 <  {chm_nosuch, NULL},                             /* F */
1154 <  {chm_nosuch, NULL},                             /* G */
1155 <  {chm_nosuch, NULL},                             /* H */
1156 <  {chm_invex, NULL},                              /* I */
1157 <  {chm_nosuch, NULL},                             /* J */
1158 <  {chm_nosuch, NULL},                             /* K */
1159 <  {chm_nosuch, NULL},                             /* L */
1160 <  {chm_nosuch, NULL},                             /* M */
1161 <  {chm_nosuch, NULL},                             /* N */
1162 <  {chm_operonly, (void *) MODE_OPERONLY},         /* O */
1163 <  {chm_nosuch, NULL},                             /* P */
1164 <  {chm_nosuch, NULL},                             /* Q */
1165 <  {chm_simple, (void *) MODE_REGONLY},            /* R */
1166 <  {chm_simple, (void *) MODE_SSLONLY},            /* S */
1167 <  {chm_nosuch, NULL},                             /* T */
1168 <  {chm_nosuch, NULL},                             /* U */
1169 <  {chm_nosuch, NULL},                             /* V */
1170 <  {chm_nosuch, NULL},                             /* W */
1171 <  {chm_nosuch, NULL},                             /* X */
1172 <  {chm_nosuch, NULL},                             /* Y */
1173 <  {chm_nosuch, NULL},                             /* Z */
1174 <  {chm_nosuch, NULL},
1175 <  {chm_nosuch, NULL},
1176 <  {chm_nosuch, NULL},
1177 <  {chm_nosuch, NULL},
1178 <  {chm_nosuch, NULL},
1179 <  {chm_nosuch, NULL},
1180 <  {chm_nosuch, NULL},                             /* a */
1181 <  {chm_ban, NULL},                                /* b */
1182 <  {chm_nosuch, NULL},                             /* c */
1183 <  {chm_nosuch, NULL},                             /* d */
1184 <  {chm_except, NULL},                             /* e */
1185 <  {chm_nosuch, NULL},                             /* f */
1186 <  {chm_nosuch, NULL},                             /* g */
1147 >  { chm_nosuch,  0 },                   /* 0x00 */
1148 >  { chm_nosuch,  0 },                   /* 0x01 */
1149 >  { chm_nosuch,  0 },                   /* 0x02 */
1150 >  { chm_nosuch,  0 },                   /* 0x03 */
1151 >  { chm_nosuch,  0 },                   /* 0x04 */
1152 >  { chm_nosuch,  0 },                   /* 0x05 */
1153 >  { chm_nosuch,  0 },                   /* 0x06 */
1154 >  { chm_nosuch,  0 },                   /* 0x07 */
1155 >  { chm_nosuch,  0 },                   /* 0x08 */
1156 >  { chm_nosuch,  0 },                   /* 0x09 */
1157 >  { chm_nosuch,  0 },                   /* 0x0a */
1158 >  { chm_nosuch,  0 },                   /* 0x0b */
1159 >  { chm_nosuch,  0 },                   /* 0x0c */
1160 >  { chm_nosuch,  0 },                   /* 0x0d */
1161 >  { chm_nosuch,  0 },                   /* 0x0e */
1162 >  { chm_nosuch,  0 },                   /* 0x0f */
1163 >  { chm_nosuch,  0 },                   /* 0x10 */
1164 >  { chm_nosuch,  0 },                   /* 0x11 */
1165 >  { chm_nosuch,  0 },                   /* 0x12 */
1166 >  { chm_nosuch,  0 },                   /* 0x13 */
1167 >  { chm_nosuch,  0 },                   /* 0x14 */
1168 >  { chm_nosuch,  0 },                   /* 0x15 */
1169 >  { chm_nosuch,  0 },                   /* 0x16 */
1170 >  { chm_nosuch,  0 },                   /* 0x17 */
1171 >  { chm_nosuch,  0 },                   /* 0x18 */
1172 >  { chm_nosuch,  0 },                   /* 0x19 */
1173 >  { chm_nosuch,  0 },                   /* 0x1a */
1174 >  { chm_nosuch,  0 },                   /* 0x1b */
1175 >  { chm_nosuch,  0 },                   /* 0x1c */
1176 >  { chm_nosuch,  0 },                   /* 0x1d */
1177 >  { chm_nosuch,  0 },                   /* 0x1e */
1178 >  { chm_nosuch,  0 },                   /* 0x1f */
1179 >  { chm_nosuch,  0 },                   /* 0x20 */
1180 >  { chm_nosuch,  0 },                   /* 0x21 */
1181 >  { chm_nosuch,  0 },                   /* 0x22 */
1182 >  { chm_nosuch,  0 },                   /* 0x23 */
1183 >  { chm_nosuch,  0 },                   /* 0x24 */
1184 >  { chm_nosuch,  0 },                   /* 0x25 */
1185 >  { chm_nosuch,  0 },                   /* 0x26 */
1186 >  { chm_nosuch,  0 },                   /* 0x27 */
1187 >  { chm_nosuch,  0 },                   /* 0x28 */
1188 >  { chm_nosuch,  0 },                   /* 0x29 */
1189 >  { chm_nosuch,  0 },                   /* 0x2a */
1190 >  { chm_nosuch,  0 },                   /* 0x2b */
1191 >  { chm_nosuch,  0 },                   /* 0x2c */
1192 >  { chm_nosuch,  0 },                   /* 0x2d */
1193 >  { chm_nosuch,  0 },                   /* 0x2e */
1194 >  { chm_nosuch,  0 },                   /* 0x2f */
1195 >  { chm_nosuch,  0 },                   /* 0x30 */
1196 >  { chm_nosuch,  0 },                   /* 0x31 */
1197 >  { chm_nosuch,  0 },                   /* 0x32 */
1198 >  { chm_nosuch,  0 },                   /* 0x33 */
1199 >  { chm_nosuch,  0 },                   /* 0x34 */
1200 >  { chm_nosuch,  0 },                   /* 0x35 */
1201 >  { chm_nosuch,  0 },                   /* 0x36 */
1202 >  { chm_nosuch,  0 },                   /* 0x37 */
1203 >  { chm_nosuch,  0 },                   /* 0x38 */
1204 >  { chm_nosuch,  0 },                   /* 0x39 */
1205 >  { chm_nosuch,  0 },                   /* 0x3a */
1206 >  { chm_nosuch,  0 },                   /* 0x3b */
1207 >  { chm_nosuch,  0 },                   /* 0x3c */
1208 >  { chm_nosuch,  0 },                   /* 0x3d */
1209 >  { chm_nosuch,  0 },                   /* 0x3e */
1210 >  { chm_nosuch,  0 },                   /* 0x3f */
1211 >  { chm_nosuch,  0 },                   /* @ */
1212 >  { chm_nosuch,  0 },                   /* A */
1213 >  { chm_nosuch,  0 },                   /* B */
1214 >  { chm_nosuch,  0 },                   /* C */
1215 >  { chm_nosuch,  0 },                   /* D */
1216 >  { chm_nosuch,  0 },                   /* E */
1217 >  { chm_nosuch,  0 },                   /* F */
1218 >  { chm_nosuch,  0 },                   /* G */
1219 >  { chm_nosuch,  0 },                   /* H */
1220 >  { chm_invex,   0 },                   /* I */
1221 >  { chm_nosuch,  0 },                   /* J */
1222 >  { chm_nosuch,  0 },                   /* K */
1223 >  { chm_nosuch,  0 },                   /* L */
1224 >  { chm_simple, MODE_MODREG},           /* M */
1225 >  { chm_nosuch,  0 },                   /* N */
1226 >  { chm_operonly, MODE_OPERONLY},       /* O */
1227 >  { chm_nosuch,  0 },                   /* P */
1228 >  { chm_nosuch,  0 },                   /* Q */
1229 >  { chm_simple, MODE_REGONLY},          /* R */
1230 >  { chm_simple, MODE_SSLONLY},          /* S */
1231 >  { chm_nosuch,  0 },                   /* T */
1232 >  { chm_nosuch,  0 },                   /* U */
1233 >  { chm_nosuch,  0 },                   /* V */
1234 >  { chm_nosuch,  0 },                   /* W */
1235 >  { chm_nosuch,  0 },                   /* X */
1236 >  { chm_nosuch,  0 },                   /* Y */
1237 >  { chm_nosuch,  0 },                   /* Z */
1238 >  { chm_nosuch,  0 },
1239 >  { chm_nosuch,  0 },
1240 >  { chm_nosuch,  0 },
1241 >  { chm_nosuch,  0 },
1242 >  { chm_nosuch,  0 },
1243 >  { chm_nosuch,  0 },
1244 >  { chm_nosuch,  0 },                   /* a */
1245 >  { chm_ban,     0 },                   /* b */
1246 >  { chm_simple, MODE_NOCTRL},           /* c */
1247 >  { chm_nosuch,  0 },                   /* d */
1248 >  { chm_except,  0 },                   /* e */
1249 >  { chm_nosuch,  0 },                   /* f */
1250 >  { chm_nosuch,  0 },                   /* g */
1251   #ifdef HALFOPS
1252 <  {chm_hop, NULL},                                /* h */
1252 >  { chm_hop,     0 },                   /* h */
1253   #else
1254 <  {chm_nosuch, NULL},                             /* h */
1254 >  { chm_nosuch,  0 },                   /* h */
1255   #endif
1256 <  {chm_simple, (void *) MODE_INVITEONLY},         /* i */
1257 <  {chm_nosuch, NULL},                             /* j */
1258 <  {chm_key, NULL},                                /* k */
1259 <  {chm_limit, NULL},                              /* l */
1260 <  {chm_simple, (void *) MODE_MODERATED},          /* m */
1261 <  {chm_simple, (void *) MODE_NOPRIVMSGS},         /* n */
1262 <  {chm_op, NULL},                                 /* o */
1263 <  {chm_simple, (void *) MODE_PRIVATE},            /* p */
1264 <  {chm_nosuch, NULL},                             /* q */
1265 <  {chm_registered, (void *) MODE_REGISTERED},     /* r */
1266 <  {chm_simple, (void *) MODE_SECRET},             /* s */
1267 <  {chm_simple, (void *) MODE_TOPICLIMIT},         /* t */
1268 <  {chm_nosuch, NULL},                             /* u */
1269 <  {chm_voice, NULL},                              /* v */
1270 <  {chm_nosuch, NULL},                             /* w */
1271 <  {chm_nosuch, NULL},                             /* x */
1272 <  {chm_nosuch, NULL},                             /* y */
1273 <  {chm_nosuch, NULL},                             /* z */
1256 >  { chm_simple,     MODE_INVITEONLY },  /* i */
1257 >  { chm_nosuch,     0               },  /* j */
1258 >  { chm_key,        0               },  /* k */
1259 >  { chm_limit,      0               },  /* l */
1260 >  { chm_simple,     MODE_MODERATED  },  /* m */
1261 >  { chm_simple,     MODE_NOPRIVMSGS },  /* n */
1262 >  { chm_op,         0               },  /* o */
1263 >  { chm_simple,     MODE_PRIVATE    },  /* p */
1264 >  { chm_nosuch,     0               },  /* q */
1265 >  { chm_registered, MODE_REGISTERED },  /* r */
1266 >  { chm_simple,     MODE_SECRET     },  /* s */
1267 >  { chm_simple,     MODE_TOPICLIMIT },  /* t */
1268 >  { chm_nosuch,     0               },  /* u */
1269 >  { chm_voice,      0               },  /* v */
1270 >  { chm_nosuch,     0               },  /* w */
1271 >  { chm_nosuch,     0               },  /* x */
1272 >  { chm_nosuch,     0               },  /* y */
1273 >  { chm_nosuch,     0               },  /* z */
1274 >  { chm_nosuch,  0 },                   /* 0x7b */
1275 >  { chm_nosuch,  0 },                   /* 0x7c */
1276 >  { chm_nosuch,  0 },                   /* 0x7d */
1277 >  { chm_nosuch,  0 },                   /* 0x7e */
1278 >  { chm_nosuch,  0 },                   /* 0x7f */
1279 >  { chm_nosuch,  0 },                   /* 0x80 */
1280 >  { chm_nosuch,  0 },                   /* 0x81 */
1281 >  { chm_nosuch,  0 },                   /* 0x82 */
1282 >  { chm_nosuch,  0 },                   /* 0x83 */
1283 >  { chm_nosuch,  0 },                   /* 0x84 */
1284 >  { chm_nosuch,  0 },                   /* 0x85 */
1285 >  { chm_nosuch,  0 },                   /* 0x86 */
1286 >  { chm_nosuch,  0 },                   /* 0x87 */
1287 >  { chm_nosuch,  0 },                   /* 0x88 */
1288 >  { chm_nosuch,  0 },                   /* 0x89 */
1289 >  { chm_nosuch,  0 },                   /* 0x8a */
1290 >  { chm_nosuch,  0 },                   /* 0x8b */
1291 >  { chm_nosuch,  0 },                   /* 0x8c */
1292 >  { chm_nosuch,  0 },                   /* 0x8d */
1293 >  { chm_nosuch,  0 },                   /* 0x8e */
1294 >  { chm_nosuch,  0 },                   /* 0x8f */
1295 >  { chm_nosuch,  0 },                   /* 0x90 */
1296 >  { chm_nosuch,  0 },                   /* 0x91 */
1297 >  { chm_nosuch,  0 },                   /* 0x92 */
1298 >  { chm_nosuch,  0 },                   /* 0x93 */
1299 >  { chm_nosuch,  0 },                   /* 0x94 */
1300 >  { chm_nosuch,  0 },                   /* 0x95 */
1301 >  { chm_nosuch,  0 },                   /* 0x96 */
1302 >  { chm_nosuch,  0 },                   /* 0x97 */
1303 >  { chm_nosuch,  0 },                   /* 0x98 */
1304 >  { chm_nosuch,  0 },                   /* 0x99 */
1305 >  { chm_nosuch,  0 },                   /* 0x9a */
1306 >  { chm_nosuch,  0 },                   /* 0x9b */
1307 >  { chm_nosuch,  0 },                   /* 0x9c */
1308 >  { chm_nosuch,  0 },                   /* 0x9d */
1309 >  { chm_nosuch,  0 },                   /* 0x9e */
1310 >  { chm_nosuch,  0 },                   /* 0x9f */
1311 >  { chm_nosuch,  0 },                   /* 0xa0 */
1312 >  { chm_nosuch,  0 },                   /* 0xa1 */
1313 >  { chm_nosuch,  0 },                   /* 0xa2 */
1314 >  { chm_nosuch,  0 },                   /* 0xa3 */
1315 >  { chm_nosuch,  0 },                   /* 0xa4 */
1316 >  { chm_nosuch,  0 },                   /* 0xa5 */
1317 >  { chm_nosuch,  0 },                   /* 0xa6 */
1318 >  { chm_nosuch,  0 },                   /* 0xa7 */
1319 >  { chm_nosuch,  0 },                   /* 0xa8 */
1320 >  { chm_nosuch,  0 },                   /* 0xa9 */
1321 >  { chm_nosuch,  0 },                   /* 0xaa */
1322 >  { chm_nosuch,  0 },                   /* 0xab */
1323 >  { chm_nosuch,  0 },                   /* 0xac */
1324 >  { chm_nosuch,  0 },                   /* 0xad */
1325 >  { chm_nosuch,  0 },                   /* 0xae */
1326 >  { chm_nosuch,  0 },                   /* 0xaf */
1327 >  { chm_nosuch,  0 },                   /* 0xb0 */
1328 >  { chm_nosuch,  0 },                   /* 0xb1 */
1329 >  { chm_nosuch,  0 },                   /* 0xb2 */
1330 >  { chm_nosuch,  0 },                   /* 0xb3 */
1331 >  { chm_nosuch,  0 },                   /* 0xb4 */
1332 >  { chm_nosuch,  0 },                   /* 0xb5 */
1333 >  { chm_nosuch,  0 },                   /* 0xb6 */
1334 >  { chm_nosuch,  0 },                   /* 0xb7 */
1335 >  { chm_nosuch,  0 },                   /* 0xb8 */
1336 >  { chm_nosuch,  0 },                   /* 0xb9 */
1337 >  { chm_nosuch,  0 },                   /* 0xba */
1338 >  { chm_nosuch,  0 },                   /* 0xbb */
1339 >  { chm_nosuch,  0 },                   /* 0xbc */
1340 >  { chm_nosuch,  0 },                   /* 0xbd */
1341 >  { chm_nosuch,  0 },                   /* 0xbe */
1342 >  { chm_nosuch,  0 },                   /* 0xbf */
1343 >  { chm_nosuch,  0 },                   /* 0xc0 */
1344 >  { chm_nosuch,  0 },                   /* 0xc1 */
1345 >  { chm_nosuch,  0 },                   /* 0xc2 */
1346 >  { chm_nosuch,  0 },                   /* 0xc3 */
1347 >  { chm_nosuch,  0 },                   /* 0xc4 */
1348 >  { chm_nosuch,  0 },                   /* 0xc5 */
1349 >  { chm_nosuch,  0 },                   /* 0xc6 */
1350 >  { chm_nosuch,  0 },                   /* 0xc7 */
1351 >  { chm_nosuch,  0 },                   /* 0xc8 */
1352 >  { chm_nosuch,  0 },                   /* 0xc9 */
1353 >  { chm_nosuch,  0 },                   /* 0xca */
1354 >  { chm_nosuch,  0 },                   /* 0xcb */
1355 >  { chm_nosuch,  0 },                   /* 0xcc */
1356 >  { chm_nosuch,  0 },                   /* 0xcd */
1357 >  { chm_nosuch,  0 },                   /* 0xce */
1358 >  { chm_nosuch,  0 },                   /* 0xcf */
1359 >  { chm_nosuch,  0 },                   /* 0xd0 */
1360 >  { chm_nosuch,  0 },                   /* 0xd1 */
1361 >  { chm_nosuch,  0 },                   /* 0xd2 */
1362 >  { chm_nosuch,  0 },                   /* 0xd3 */
1363 >  { chm_nosuch,  0 },                   /* 0xd4 */
1364 >  { chm_nosuch,  0 },                   /* 0xd5 */
1365 >  { chm_nosuch,  0 },                   /* 0xd6 */
1366 >  { chm_nosuch,  0 },                   /* 0xd7 */
1367 >  { chm_nosuch,  0 },                   /* 0xd8 */
1368 >  { chm_nosuch,  0 },                   /* 0xd9 */
1369 >  { chm_nosuch,  0 },                   /* 0xda */
1370 >  { chm_nosuch,  0 },                   /* 0xdb */
1371 >  { chm_nosuch,  0 },                   /* 0xdc */
1372 >  { chm_nosuch,  0 },                   /* 0xdd */
1373 >  { chm_nosuch,  0 },                   /* 0xde */
1374 >  { chm_nosuch,  0 },                   /* 0xdf */
1375 >  { chm_nosuch,  0 },                   /* 0xe0 */
1376 >  { chm_nosuch,  0 },                   /* 0xe1 */
1377 >  { chm_nosuch,  0 },                   /* 0xe2 */
1378 >  { chm_nosuch,  0 },                   /* 0xe3 */
1379 >  { chm_nosuch,  0 },                   /* 0xe4 */
1380 >  { chm_nosuch,  0 },                   /* 0xe5 */
1381 >  { chm_nosuch,  0 },                   /* 0xe6 */
1382 >  { chm_nosuch,  0 },                   /* 0xe7 */
1383 >  { chm_nosuch,  0 },                   /* 0xe8 */
1384 >  { chm_nosuch,  0 },                   /* 0xe9 */
1385 >  { chm_nosuch,  0 },                   /* 0xea */
1386 >  { chm_nosuch,  0 },                   /* 0xeb */
1387 >  { chm_nosuch,  0 },                   /* 0xec */
1388 >  { chm_nosuch,  0 },                   /* 0xed */
1389 >  { chm_nosuch,  0 },                   /* 0xee */
1390 >  { chm_nosuch,  0 },                   /* 0xef */
1391 >  { chm_nosuch,  0 },                   /* 0xf0 */
1392 >  { chm_nosuch,  0 },                   /* 0xf1 */
1393 >  { chm_nosuch,  0 },                   /* 0xf2 */
1394 >  { chm_nosuch,  0 },                   /* 0xf3 */
1395 >  { chm_nosuch,  0 },                   /* 0xf4 */
1396 >  { chm_nosuch,  0 },                   /* 0xf5 */
1397 >  { chm_nosuch,  0 },                   /* 0xf6 */
1398 >  { chm_nosuch,  0 },                   /* 0xf7 */
1399 >  { chm_nosuch,  0 },                   /* 0xf8 */
1400 >  { chm_nosuch,  0 },                   /* 0xf9 */
1401 >  { chm_nosuch,  0 },                   /* 0xfa */
1402 >  { chm_nosuch,  0 },                   /* 0xfb */
1403 >  { chm_nosuch,  0 },                   /* 0xfc */
1404 >  { chm_nosuch,  0 },                   /* 0xfd */
1405 >  { chm_nosuch,  0 },                   /* 0xfe */
1406 >  { chm_nosuch,  0 },                   /* 0xff */
1407   };
1408  
1409   /* get_channel_access()
# Line 1471 | Line 1415 | static struct ChannelMode ModeTable[255]
1415   * side effects - NONE
1416   */
1417   static int
1418 < get_channel_access(struct Client *source_p, struct Membership *member)
1418 > get_channel_access(const struct Client *source_p,
1419 >                   const struct Membership *member)
1420   {
1421    /* Let hacked servers in for now... */
1422    if (!MyClient(source_p))
# Line 1516 | Line 1461 | get_channel_access(struct Client *source
1461   /* rewritten to ensure parabuf < MODEBUFLEN -db */
1462  
1463   static void
1464 < send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
1465 <                      struct Channel *chptr, unsigned int cap, unsigned int nocap)
1464 > send_mode_changes_server(struct Client *client_p, struct Client *source_p,
1465 >                         struct Channel *chptr)
1466   {
1467 <  int i, mbl, pbl, arglen, nc, mc;
1467 >  unsigned int i;
1468 >  int mbl, pbl, arglen, nc, mc;
1469    int len;
1470    const char *arg = NULL;
1471    char *parptr;
# Line 1532 | Line 1478 | send_cap_mode_changes(struct Client *cli
1478    parabuf[0] = '\0';
1479    parptr = parabuf;
1480  
1481 <  if ((cap & CAP_TS6) && source_p->id[0] != '\0')
1482 <    mbl = ircsprintf(modebuf, ":%s TMODE %lu %s ", source_p->id,
1537 <                     (unsigned long)chptr->channelts, chptr->chname);
1538 <  else
1539 <    mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->name,
1540 <                     chptr->chname);
1481 >  mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %lu %s ", source_p->id,
1482 >                 (unsigned long)chptr->channelts, chptr->chname);
1483  
1484    /* loop the list of - modes we have */
1485 <  for (i = 0; i < mode_count; i++)
1485 >  for (i = 0; i < mode_count; ++i)
1486    {
1487      /* if they dont support the cap we need, or they do support a cap they
1488       * cant have, then dont add it to the modebuf.. that way they wont see
1489       * the mode
1490       */
1491 <    if ((mode_changes[i].letter == 0) ||
1550 <        ((cap & mode_changes[i].caps) != mode_changes[i].caps)
1551 <        || ((nocap & mode_changes[i].nocaps) != mode_changes[i].nocaps))
1491 >    if (mode_changes[i].letter == 0) /* XXX: can it ever happen? */
1492        continue;
1493  
1494 <    arg = "";
1555 <
1556 <    if ((cap & CAP_TS6) && mode_changes[i].id)
1494 >    if (mode_changes[i].id)
1495        arg = mode_changes[i].id;
1496 <    if (*arg == '\0')
1496 >    else
1497        arg = mode_changes[i].arg;
1498  
1561    /* if we're creeping past the buf size, we need to send it and make
1562     * another line for the other modes
1563     * XXX - this could give away server topology with uids being
1564     * different lengths, but not much we can do, except possibly break
1565     * them as if they were the longest of the nick or uid at all times,
1566     * which even then won't work as we don't always know the uid -A1kmm.
1567     */
1499      if (arg != NULL)
1500        arglen = strlen(arg);
1501      else
1502        arglen = 0;
1503  
1504 +
1505 +    /*
1506 +     * If we're creeping past the buf size, we need to send it and make
1507 +     * another line for the other modes
1508 +     */
1509      if ((mc == MAXMODEPARAMS) ||
1510          ((arglen + mbl + pbl + 2) > IRCD_BUFSIZE) ||
1511          (pbl + arglen + BAN_FUDGE) >= MODEBUFLEN)
1512      {
1513        if (nc != 0)
1514 <        sendto_server(client_p, cap, nocap,
1579 <                      "%s %s",
1580 <                      modebuf, parabuf);
1514 >        sendto_server(client_p, NOCAPS, NOCAPS, "%s %s", modebuf, parabuf);
1515        nc = 0;
1516        mc = 0;
1517  
1518 <      if ((cap & CAP_TS6) && source_p->id[0] != '\0')
1519 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->id,
1586 <                         chptr->chname);
1587 <      else
1588 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->name,
1589 <                         chptr->chname);
1518 >      mbl = snprintf(modebuf, sizeof(modebuf), ":%s TMODE %lu %s ", source_p->id,
1519 >                     (unsigned long)chptr->channelts, chptr->chname);
1520  
1521        pbl = 0;
1522        parabuf[0] = '\0';
# Line 1606 | Line 1536 | send_cap_mode_changes(struct Client *cli
1536  
1537      if (arg != NULL)
1538      {
1539 <      len = ircsprintf(parptr, "%s ", arg);
1539 >      len = sprintf(parptr, "%s ", arg);
1540        pbl += len;
1541        parptr += len;
1542        mc++;
# Line 1614 | Line 1544 | send_cap_mode_changes(struct Client *cli
1544    }
1545  
1546    if (pbl && parabuf[pbl - 1] == ' ')
1547 <    parabuf[pbl - 1] = 0;
1547 >    parabuf[pbl - 1] = '\0';
1548  
1549    if (nc != 0)
1550 <    sendto_server(client_p, cap, nocap,
1621 <                  "%s %s", modebuf, parabuf);
1550 >    sendto_server(client_p, NOCAPS, NOCAPS, "%s %s", modebuf, parabuf);
1551   }
1552  
1553   /* void send_mode_changes(struct Client *client_p,
# Line 1634 | Line 1563 | send_cap_mode_changes(struct Client *cli
1563   /* ensure parabuf < MODEBUFLEN -db */
1564   static void
1565   send_mode_changes(struct Client *client_p, struct Client *source_p,
1566 <                  struct Channel *chptr, char *chname)
1566 >                  struct Channel *chptr)
1567   {
1568 <  int i, mbl, pbl, arglen, nc, mc;
1568 >  unsigned int i;
1569 >  int mbl, pbl, arglen, nc, mc;
1570    int len;
1571    const char *arg = NULL;
1572    char *parptr;
# Line 1647 | Line 1577 | send_mode_changes(struct Client *client_
1577      return;
1578  
1579    if (IsServer(source_p))
1580 <    mbl = ircsprintf(modebuf, ":%s MODE %s ", (IsHidden(source_p) ||
1581 <                     ConfigServerHide.hide_servers) ?
1582 <                     me.name : source_p->name, chname);
1580 >    mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1581 >                   ConfigServerHide.hide_servers) ?
1582 >                   me.name : source_p->name, chptr->chname);
1583    else
1584 <    mbl = ircsprintf(modebuf, ":%s!%s@%s MODE %s ", source_p->name,
1585 <                     source_p->username, source_p->host, chname);
1584 >    mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1585 >                   source_p->username, source_p->host, chptr->chname);
1586  
1587    mc = 0;
1588    nc = 0;
# Line 1661 | Line 1591 | send_mode_changes(struct Client *client_
1591    parabuf[0] = '\0';
1592    parptr = parabuf;
1593  
1594 <  for (i = 0; i < mode_count; i++)
1594 >  for (i = 0; i < mode_count; ++i)
1595    {
1596      if (mode_changes[i].letter == 0 ||
1597          mode_changes[i].mems == NON_CHANOPS ||
# Line 1674 | Line 1604 | send_mode_changes(struct Client *client_
1604      else
1605        arglen = 0;
1606  
1607 <    if ((mc == MAXMODEPARAMS)  ||
1607 >    if ((mc == MAXMODEPARAMS)  ||
1608          ((arglen + mbl + pbl + 2) > IRCD_BUFSIZE) ||
1609 <        ((arglen + pbl + BAN_FUDGE) >= MODEBUFLEN))
1609 >        ((arglen + pbl + BAN_FUDGE) >= MODEBUFLEN))
1610      {
1611        if (mbl && modebuf[mbl - 1] == '-')
1612          modebuf[mbl - 1] = '\0';
# Line 1688 | Line 1618 | send_mode_changes(struct Client *client_
1618        mc = 0;
1619  
1620        if (IsServer(source_p))
1621 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", me.name, chname);
1621 >        mbl = snprintf(modebuf, sizeof(modebuf), ":%s MODE %s ", (IsHidden(source_p) ||
1622 >                       ConfigServerHide.hide_servers) ?
1623 >                       me.name : source_p->name, chptr->chname);
1624        else
1625 <        mbl = ircsprintf(modebuf, ":%s!%s@%s MODE %s ", source_p->name,
1626 <                         source_p->username, source_p->host, chname);
1625 >        mbl = snprintf(modebuf, sizeof(modebuf), ":%s!%s@%s MODE %s ", source_p->name,
1626 >                       source_p->username, source_p->host, chptr->chname);
1627  
1628        pbl = 0;
1629        parabuf[0] = '\0';
# Line 1711 | Line 1643 | send_mode_changes(struct Client *client_
1643  
1644      if (arg != NULL)
1645      {
1646 <      len = ircsprintf(parptr, "%s ", arg);
1646 >      len = sprintf(parptr, "%s ", arg);
1647        pbl += len;
1648        parptr += len;
1649        mc++;
# Line 1719 | Line 1651 | send_mode_changes(struct Client *client_
1651    }
1652  
1653    if (pbl && parabuf[pbl - 1] == ' ')
1654 <    parabuf[pbl - 1] = 0;
1654 >    parabuf[pbl - 1] = '\0';
1655  
1656    if (nc != 0)
1657      sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
# Line 1727 | Line 1659 | send_mode_changes(struct Client *client_
1659    nc = 0;
1660    mc = 0;
1661  
1662 <  /* Now send to servers... */
1731 <  for (i = 0; i < NCHCAP_COMBOS; i++)
1732 <    if (chcap_combos[i].count != 0)
1733 <      send_cap_mode_changes(client_p, source_p, chptr,
1734 <                            chcap_combos[i].cap_yes,
1735 <                            chcap_combos[i].cap_no);
1662 >  send_mode_changes_server(client_p, source_p, chptr);
1663   }
1664  
1665   /* void set_channel_mode(struct Client *client_p, struct Client *source_p,
# Line 1748 | Line 1675 | send_mode_changes(struct Client *client_
1675   */
1676   void
1677   set_channel_mode(struct Client *client_p, struct Client *source_p, struct Channel *chptr,
1678 <                 struct Membership *member, int parc, char *parv[], char *chname)
1678 >                 struct Membership *member, int parc, char *parv[])
1679   {
1680    int dir = MODE_ADD;
1681    int parn = 1;
1682    int alevel, errors = 0;
1683    char *ml = parv[0], c;
1757  int table_position;
1684  
1685    mode_count = 0;
1686    mode_limit = 0;
# Line 1762 | Line 1688 | set_channel_mode(struct Client *client_p
1688  
1689    alevel = get_channel_access(source_p, member);
1690  
1691 <  for (; (c = *ml) != '\0'; ml++)
1691 >  for (; (c = *ml); ++ml)
1692    {
1767 #if 0
1768    if(mode_count > 20)
1769      break;
1770 #endif
1693      switch (c)
1694      {
1695        case '+':
# Line 1780 | Line 1702 | set_channel_mode(struct Client *client_p
1702          dir = MODE_QUERY;
1703          break;
1704        default:
1705 <        if (c < 'A' || c > 'z')
1706 <          table_position = 0;
1707 <        else
1708 <          table_position = c - 'A' + 1;
1709 <        ModeTable[table_position].func(client_p, source_p, chptr,
1788 <                                       parc, &parn,
1789 <                                       parv, &errors, alevel, dir, c,
1790 <                                       ModeTable[table_position].d,
1791 <                                       chname);
1705 >      {
1706 >        struct ChannelMode *tptr = &ModeTable[(unsigned char)c];
1707 >
1708 >        tptr->func(client_p, source_p, chptr, parc, &parn,
1709 >                   parv, &errors, alevel, dir, c, tptr->d);
1710          break;
1711 +      }
1712      }
1713    }
1714  
1715 <  send_mode_changes(client_p, source_p, chptr, chname);
1715 >  send_mode_changes(client_p, source_p, chptr);
1716   }

Diff Legend

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