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

Comparing:
ircd-hybrid-7.2/src/channel_mode.c (file contents), Revision 356 by adx, Mon Jan 2 22:05:15 2006 UTC vs.
ircd-hybrid/trunk/src/channel_mode.c (file contents), 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"
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 < #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  
109 /* XXX check_string is propably not longer required in add_id and del_id */
74   /* check_string()
75   *
76   * inputs       - string to check
# Line 122 | 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 134 | Line 98 | check_string(char *s)
98      }
99    }
100  
101 <  return (str);
101 >  return EmptyString(str) ? star : str;
102   }
103  
104   /*
105   * Ban functions to work with mode +b/e/d/I
106   */
107 < /* add the specified ID to the channel..
108 < *   -is 8/9/00
107 > /* add the specified ID to the channel.
108 > *   -is 8/9/00
109   */
110  
111   int
112 < add_id(struct Client *client_p, struct Channel *chptr, char *banid, int type)
112 > add_id(struct Client *client_p, struct Channel *chptr, char *banid, unsigned int type)
113   {
114 <  dlink_list *list;
115 <  dlink_node *ban;
114 >  dlink_list *list = NULL;
115 >  dlink_node *ban = NULL;
116    size_t len = 0;
117 <  struct Ban *actualBan;
117 >  struct Ban *ban_p = NULL;
118    unsigned int num_mask;
119 <  char *name = NULL, *user = NULL, *host = NULL;
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 163 | 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),
167 <                 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 199 | 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 <    {
207 <      MyFree(name);
208 <      MyFree(user);
209 <      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;
211    }
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",
228 <               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 243 | 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;
225 >  char name[NICKLEN + 1];
226 >  char user[USERLEN + 1];
227 >  char host[HOSTLEN + 1];
228 >  struct split_nuh_item nuh;
229 >
230 >  assert(banid);
231 >
232 >  nuh.nuhmask  = check_string(banid);
233 >  nuh.nickptr  = name;
234 >  nuh.userptr  = user;
235 >  nuh.hostptr  = host;
236 >
237 >  nuh.nicksize = sizeof(name);
238 >  nuh.usersize = sizeof(user);
239 >  nuh.hostsize = sizeof(host);
240  
241 <  split_nuh(check_string(banid), &name, &user, &host);
241 >  split_nuh(&nuh);
242  
243    /*
244 <   * Assemble a n!u@h and print it back to banid for sending
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 275 | 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,
264 <                           "del_id() called with unknown ban type %d!", type);
280 <      MyFree(name);
281 <      MyFree(user);
282 <      MyFree(host);
283 <      return(0);
263 >      assert(0);
264 >      return 0;
265    }
266  
267    DLINK_FOREACH(ban, list->head)
# Line 288 | 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) &&
273 <        !irccmp(host, banptr->host))
272 >        !irccmp(user, banptr->user) &&
273 >        !irccmp(host, banptr->host))
274      {
275        remove_ban(banptr, list);
295      MyFree(name);
296      MyFree(user);
297      MyFree(host);
276        return 1;
277      }
278    }
279  
302  MyFree(name);
303  MyFree(user);
304  MyFree(host);
280    return 0;
281   }
282  
308 static const struct mode_letter
309 {
310  const unsigned int mode;
311  const unsigned char letter;
312 } flags[] = {
313  { MODE_INVITEONLY, 'i' },
314  { MODE_MODERATED,  'm' },
315  { MODE_NOPRIVMSGS, 'n' },
316  { MODE_PRIVATE,    'p' },
317  { MODE_SECRET,     's' },
318  { MODE_TOPICLIMIT, 't' },
319  { 0, '\0' }
320 };
321
283   /* channel_modes()
284   *
285   * inputs       - pointer to channel
# Line 333 | Line 294 | void
294   channel_modes(struct Channel *chptr, struct Client *client_p,
295                char *mbuf, char *pbuf)
296   {
297 <  int i;
297 >  const struct mode_letter *tab = chan_modes;
298  
299    *mbuf++ = '+';
300    *pbuf = '\0';
301  
302 <  for (i = 0; flags[i].mode; ++i)
303 <    if (chptr->mode.mode & flags[i].mode)
304 <      *mbuf++ = flags[i].letter;
302 >  for (; tab->mode; ++tab)
303 >    if (chptr->mode.mode & tab->mode)
304 >      *mbuf++ = tab->letter;
305  
306    if (chptr->mode.limit)
307    {
308      *mbuf++ = 'l';
309  
310 <    if (IsMember(client_p, chptr) || IsServer(client_p))
311 <      pbuf += ircsprintf(pbuf, "%d ", chptr->mode.limit);
310 >    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
311 >      pbuf += sprintf(pbuf, "%d ", chptr->mode.limit);
312    }
313  
314    if (chptr->mode.key[0])
315    {
316      *mbuf++ = 'k';
317  
318 <    if (*pbuf || IsMember(client_p, chptr) || IsServer(client_p))
319 <      ircsprintf(pbuf, "%s ", chptr->mode.key);
318 >    if (IsServer(client_p) || HasFlag(client_p, FLAGS_SERVICE) || IsMember(client_p, chptr))
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 374 | 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 399 | 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 <
417 < #define SM_ERR_NOTS         0x00000001 /* No TS on channel  */
418 < #define SM_ERR_NOOPS        0x00000002 /* No chan ops       */
419 < #define SM_ERR_UNKNOWN      0x00000004
420 < #define SM_ERR_RPL_B        0x00000008
421 < #define SM_ERR_RPL_E        0x00000010
422 < #define SM_ERR_NOTONCHANNEL 0x00000020 /* Not on channel    */
423 < #define SM_ERR_RPL_I        0x00000040
424 <
425 < /* Now lets do some stuff to keep track of what combinations of
426 < * servers exist...
427 < * Note that the number of combinations doubles each time you add
428 < * something to this list. Each one is only quick if no servers use that
429 < * combination, but if the numbers get too high here MODE will get too
430 < * slow. I suggest if you get more than 7 here, you consider getting rid
431 < * of some and merging or something. If it wasn't for irc+cs we would
432 < * probably not even need to bother about most of these, but unfortunately
433 < * we do. -A1kmm
434 < */
435 <
436 < /* void init_chcap_usage_counts(void)
437 < *
438 < * Inputs       - none
439 < * Output       - none
440 < * Side-effects - Initialises the usage counts to zero. Fills in the
441 < *                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;
447 <
448 <  memset(chcap_combos, 0, sizeof(chcap_combos));
385 >  dlink_node *ptr = NULL;
386  
387 <  /* For every possible combination */
451 <  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)
457 <        n |= channel_capabs[c];
458 <      else
459 <        y |= channel_capabs[c];
460 <    }
461 <    chcap_combos[m].cap_yes = y;
462 <    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  
466 /* void set_chcap_usage_counts(struct Client *serv_p)
467 * Input: serv_p; The client whose capabs to register.
468 * Output: none
469 * Side-effects: Increments the usage counts for the correct capab
470 *               combination.
471 */
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) &&
481 <        ((serv_p->localClient->caps & chcap_combos[n].cap_no) == 0))
482 <    {
483 <      chcap_combos[n].count++;
484 <      return;
485 <    }
403 >    struct Membership *ms = ptr->data;
404 >    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
405    }
487
488  /* This should be impossible -A1kmm. */
489  assert(0);
406   }
407  
408 < /* void set_chcap_usage_counts(struct Client *serv_p)
409 < *
494 < * Inputs       - serv_p; The client whose capabs to register.
495 < * Output       - none
496 < * Side-effects - Decrements the usage counts for the correct capab
497 < *                combination.
408 > /* bitmasks for various error returns that set_channel_mode should only return
409 > * once per call  -orabidoo
410   */
499 void
500 unset_chcap_usage_counts(struct Client *serv_p)
501 {
502  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--;
513 <      return;
514 <    }
515 <  }
516 <
517 <  /* This should be impossible -A1kmm. */
518 <  assert(0);
519 < }
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,
526 <           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,
533 <             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 > {
440 >  if ((alev < CHACCESS_HALFOP) ||
441 >      ((d == MODE_PRIVATE) && (alev < CHACCESS_CHANOP)))
442 >  {
443 >    if (!(*errors & SM_ERR_NOOPS))
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 & d)
453 >    return;
454 >
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 & d)) */
466 >  {
467 >    chptr->mode.mode |= d;
468 >
469 >    mode_changes[mode_count].letter = c;
470 >    mode_changes[mode_count].dir = MODE_ADD;
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 & d)) */
476 >  {
477 >    /* setting - */
478 >
479 >    chptr->mode.mode &= ~d;
480 >
481 >    mode_changes[mode_count].letter = c;
482 >    mode_changes[mode_count].dir = MODE_DEL;
483 >    mode_changes[mode_count].mems = ALL_MEMBERS;
484 >    mode_changes[mode_count].id = NULL;
485 >    mode_changes[mode_count++].arg = NULL;
486 >  }
487 > }
488 >
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, unsigned int d)
493   {
494 <  long mode_type;
494 >  if (!IsServer(source_p) && !HasFlag(source_p, FLAGS_SERVICE))
495 >  {
496 >    if (!(*errors & SM_ERR_ONLYSERVER))
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 <  mode_type = (long)d;
504 >  /* If have already dealt with this simple mode, ignore it */
505 >  if (simple_modes_mask & d)
506 >    return;
507 >
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
517 +   */
518 +  if (dir == MODE_ADD) /* && !(chptr->mode.mode & d)) */
519 +  {
520 +    chptr->mode.mode |= d;
521 +
522 +    mode_changes[mode_count].letter = c;
523 +    mode_changes[mode_count].dir = MODE_ADD;
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 & d)) */
529 +  {
530 +    /* setting - */
531 +
532 +    chptr->mode.mode &= ~d;
533 +
534 +    mode_changes[mode_count].letter = c;
535 +    mode_changes[mode_count].dir = MODE_DEL;
536 +    mode_changes[mode_count].mems = ALL_MEMBERS;
537 +    mode_changes[mode_count].id = NULL;
538 +    mode_changes[mode_count++].arg = NULL;
539 +  }
540 + }
541 +
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, unsigned int d)
546 + {
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    }
557 +  else if (MyClient(source_p) && !HasUMode(source_p, UMODE_OPER))
558 +  {
559 +    if (!(*errors & SM_ERR_NOTOPER))
560 +    {
561 +      if (alev == CHACCESS_NOTONCHAN)
562 +        sendto_one_numeric(source_p, &me, ERR_NOTONCHANNEL, chptr->chname);
563 +      else
564 +        sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
565 +    }
566 +
567 +    *errors |= SM_ERR_NOTOPER;
568 +    return;
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 <  /* setting + */
563 <  /* Apparently, (though no one has ever told the hybrid group directly)
564 <   * admins don't like redundant mode checking. ok. It would have been nice
565 <   * if you had have told us directly. I've left the original code snippets
566 <   * in place.
567 <   *
568 <   * -Dianora
569 <   */
570 <  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;
576    mode_changes[mode_count].caps = 0;
577    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;
590    mode_changes[mode_count].caps = 0;
591    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 598 | Line 602 | chm_simple(struct Client *client_p, stru
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,
602 <        const char *chname)
605 >        char **parv, int *errors, int alev, int dir, char c, unsigned int d)
606   {
607    char *mask = NULL;
608  
# Line 615 | 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,
621 <                 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,
625 <               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 639 | Line 640 | chm_ban(struct Client *client_p, struct
640    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
641      return;
642  
643 <  mask = parv[(*parn)++];
644 <  
643 >  mask = nuh_mask[*parn];
644 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
645 >  ++*parn;
646 >
647    if (IsServer(client_p))
648      if (strchr(mask, ' '))
649        return;
# Line 652 | Line 655 | chm_ban(struct Client *client_p, struct
655          return;
656        break;
657      case MODE_DEL:
655 /* XXX grrrrrrr */
656 #ifdef NO_BAN_COOKIE
658        if (!del_id(chptr, mask, CHFL_BAN))
659          return;
659 #else
660     /* XXX this hack allows /mode * +o-b nick ban.cookie
661      * I'd like to see this hack go away in the future.
662      */
663      del_id(chptr, mask, CHFL_BAN);
664 #endif
660        break;
661      default:
662        assert(0);
# Line 669 | Line 664 | chm_ban(struct Client *client_p, struct
664  
665    mode_changes[mode_count].letter = c;
666    mode_changes[mode_count].dir = dir;
672  mode_changes[mode_count].caps = 0;
673  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 679 | 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,
683 <           const char *chname)
675 >           char **parv, int *errors, int alev, int dir, char c, unsigned int d)
676   {
677    char *mask = NULL;
678  
687  /* if we have +e disabled, allow local clients to do anything but
688   * set the mode.  This prevents the abuse of +e when just a few
689   * servers support it. --fl
690   */
691  if (!ConfigChannel.use_except && MyClient(source_p) &&
692      ((dir == MODE_ADD) && (parc > *parn)))
693  {
694    if (*errors & SM_ERR_RPL_E)
695      return;
696
697    *errors |= SM_ERR_RPL_E;
698    return;
699  }
700
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 720 | 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,
730 <               source_p->name, chname);
707 >    sendto_one_numeric(source_p, &me, RPL_ENDOFEXCEPTLIST, chptr->chname);
708      return;
709    }
710  
711    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
712      return;
713  
714 <  mask = parv[(*parn)++];
714 >  mask = nuh_mask[*parn];
715 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
716 >  ++*parn;
717  
718    if (IsServer(client_p))
719      if (strchr(mask, ' '))
# Line 756 | Line 735 | chm_except(struct Client *client_p, stru
735  
736    mode_changes[mode_count].letter = c;
737    mode_changes[mode_count].dir = dir;
738 <  mode_changes[mode_count].caps = CAP_EX;
760 <  mode_changes[mode_count].nocaps = 0;
761 <
762 <  if (ConfigChannel.use_except)
763 <    mode_changes[mode_count].mems = ONLY_CHANOPS;
764 <  else
765 <    mode_changes[mode_count].mems = ONLY_SERVERS;
766 <
738 >  mode_changes[mode_count].mems = ONLY_CHANOPS;
739    mode_changes[mode_count].id = NULL;
740    mode_changes[mode_count++].arg = mask;
741   }
# Line 771 | 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,
775 <          const char *chname)
746 >          char **parv, int *errors, int alev, int dir, char c, unsigned int d)
747   {
748    char *mask = NULL;
749  
779  /* if we have +I disabled, allow local clients to do anything but
780   * set the mode.  This prevents the abuse of +I when just a few
781   * servers support it --fl
782   */
783  if (!ConfigChannel.use_invex && MyClient(source_p) &&
784      (dir == MODE_ADD) && (parc > *parn))
785  {
786    if (*errors & SM_ERR_RPL_I)
787      return;
788    
789    *errors |= SM_ERR_RPL_I;
790    return;
791  }
792
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 812 | 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,
822 <               source_p->name, chname);
778 >    sendto_one_numeric(source_p, &me, RPL_ENDOFINVITELIST, chptr->chname);
779      return;
780    }
781  
782    if (MyClient(source_p) && (++mode_limit > MAXMODEPARAMS))
783      return;
784  
785 <  mask = parv[(*parn)++];
785 >  mask = nuh_mask[*parn];
786 >  memcpy(mask, parv[*parn], sizeof(nuh_mask[*parn]));
787 >  ++*parn;
788  
789    if (IsServer(client_p))
790      if (strchr(mask, ' '))
# Line 848 | Line 806 | chm_invex(struct Client *client_p, struc
806  
807    mode_changes[mode_count].letter = c;
808    mode_changes[mode_count].dir = dir;
809 <  mode_changes[mode_count].caps = CAP_IE;
852 <  mode_changes[mode_count].nocaps = 0;
853 <
854 <  if (ConfigChannel.use_invex)
855 <    mode_changes[mode_count].mems = ONLY_CHANOPS;
856 <  else
857 <    mode_changes[mode_count].mems = ONLY_SERVERS;
858 <
809 >  mode_changes[mode_count].mems = ONLY_CHANOPS;
810    mode_changes[mode_count].id = NULL;
811    mode_changes[mode_count++].arg = mask;
812   }
813  
863 /*
864 * inputs       - pointer to channel
865 * output       - none
866 * side effects - clear ban cache
867 */
868 void
869 clear_ban_cache(struct Channel *chptr)
870 {
871  dlink_node *ptr = NULL;
872
873  DLINK_FOREACH(ptr, chptr->locmembers.head)
874  {
875    struct Membership *ms = ptr->data;
876    ms->flags &= ~(CHFL_BAN_SILENCED|CHFL_BAN_CHECKED);
877  }
878 }
879
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,
884 <       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;
889  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),
915 <                 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 921 | 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))
927 <  {
928 < #ifdef HALFOPS
929 <    if (has_member_flags(member, CHFL_HALFOP))
930 <      chm_hop(client_p, source_p, chptr, parc, parn, parv, errors, alev,
931 <              dir, c, d, chname);
932 < #endif
857 >  if (dir == MODE_DEL && !has_member_flags(member, CHFL_VOICE))
858      return;
934  }
935
936 #ifdef HALFOPS
937  if (dir == MODE_ADD && has_member_flags(member, CHFL_HALFOP))
938  {
939    /* promoting from % to @ is visible only to CAP_HOPS servers */
940    mode_changes[mode_count].letter = 'h';
941    mode_changes[mode_count].dir = MODE_DEL;
942    mode_changes[mode_count].caps = caps = CAP_HOPS;
943    mode_changes[mode_count].nocaps = 0;
944    mode_changes[mode_count].mems = ALL_MEMBERS;
945    mode_changes[mode_count].id = NULL;
946    mode_changes[mode_count].arg = targ_p->name;
947    mode_changes[mode_count++].client = targ_p;
948  }
949 #endif
859  
860 <  mode_changes[mode_count].letter = 'o';
860 >  mode_changes[mode_count].letter = 'v';
861    mode_changes[mode_count].dir = dir;
953  mode_changes[mode_count].caps = caps;
954  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 <  {
962 <    AddMemberFlag(member, CHFL_CHANOP);
963 <    DelMemberFlag(member, CHFL_DEOPPED | CHFL_HALFOP);
964 <  }
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,
974 <       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 994 | 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 1006 | 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),
1018 <                 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 1024 | 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;
1034  mode_changes[mode_count].caps = CAP_HOPS;
1035  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;
1040 <
1041 <  mode_changes[mode_count].letter = 'o';
1042 <  mode_changes[mode_count].dir = dir;
1043 <  mode_changes[mode_count].caps = 0;
1044 <  mode_changes[mode_count].nocaps = CAP_HOPS;
1045 <  mode_changes[mode_count].mems = ONLY_SERVERS;
1046 <  mode_changes[mode_count].id = targ_p->id;
1047 <  mode_changes[mode_count].arg = targ_p->name;
1048 <  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 1058 | 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,
1064 <          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),
1094 <                 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 1100 | 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;
1110  mode_changes[mode_count].caps = 0;
1111  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,
1127 <          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 1149 | 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++)
1156    {
1046        if (mode_changes[i].letter == c && mode_changes[i].dir == MODE_ADD)
1047          mode_changes[i].letter = 0;
1159    }
1048  
1049      mode_changes[mode_count].letter = c;
1050      mode_changes[mode_count].dir = MODE_ADD;
1163    mode_changes[mode_count].caps = 0;
1164    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 1177 | 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;
1180    mode_changes[mode_count].caps = 0;
1181    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 1188 | 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,
1192 <        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 1224 | 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++)
1227    {
1110        if (mode_changes[i].letter == c && mode_changes[i].dir == MODE_ADD)
1111          mode_changes[i].letter = 0;
1230    }
1112  
1113      mode_changes[mode_count].letter = c;
1114      mode_changes[mode_count].dir = MODE_ADD;
1234    mode_changes[mode_count].caps = 0;
1235    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 1249 | 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;
1252    mode_changes[mode_count].caps = 0;
1253    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 1259 | 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);
1266 <  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 < /* *INDENT-OFF* */
1270 < 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_nosuch, NULL},                             /* O */
1163 <  {chm_nosuch, NULL},                             /* P */
1164 <  {chm_nosuch, NULL},                             /* Q */
1165 <  {chm_nosuch, NULL},                             /* R */
1166 <  {chm_nosuch, NULL},                             /* 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_nosuch, NULL},                             /* 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   };
1336 /* *INDENT-ON* */
1408  
1409   /* get_channel_access()
1410   *
# Line 1344 | 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 1389 | 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, int cap, 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 1405 | 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,
1410 <                     (unsigned long)chptr->channelts, chptr->chname);
1411 <  else
1412 <    mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->name,
1413 <                     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) ||
1423 <        ((cap & mode_changes[i].caps) != mode_changes[i].caps)
1424 <        || ((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 = "";
1428 <
1429 <    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  
1434    /* if we're creeping past the buf size, we need to send it and make
1435     * another line for the other modes
1436     * XXX - this could give away server topology with uids being
1437     * different lengths, but not much we can do, except possibly break
1438     * them as if they were the longest of the nick or uid at all times,
1439     * which even then won't work as we don't always know the uid -A1kmm.
1440     */
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, source_p, chptr, cap, nocap,
1452 <                      LL_ICHAN | LL_ICLIENT, "%s %s",
1453 <                      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,
1459 <                         chptr->chname);
1460 <      else
1461 <        mbl = ircsprintf(modebuf, ":%s MODE %s ", source_p->name,
1462 <                         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 1479 | 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 1487 | 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, source_p, chptr, cap, nocap,
1494 <                  LL_ICLIENT, "%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 1507 | 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 1520 | 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 1534 | 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 1547 | 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';
1613  
1614        if (nc != 0)
1615 <        sendto_channel_local(ALL_MEMBERS, NO, chptr, "%s %s", modebuf, parabuf);
1615 >        sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
1616  
1617        nc = 0;
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 1584 | 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 1592 | 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, NO, chptr, "%s %s", modebuf, parabuf);
1657 >    sendto_channel_local(ALL_MEMBERS, 0, chptr, "%s %s", modebuf, parabuf);
1658  
1659    nc = 0;
1660    mc = 0;
1661  
1662 <  /* Now send to servers... */
1604 <  for (i = 0; i < NCHCAP_COMBOS; i++)
1605 <    if (chcap_combos[i].count != 0)
1606 <      send_cap_mode_changes(client_p, source_p, chptr,
1607 <                            chcap_combos[i].cap_yes,
1608 <                            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 1621 | 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;
1630  int table_position;
1684  
1685    mode_count = 0;
1686    mode_limit = 0;
# Line 1635 | 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    {
1640 #if 0
1641    if(mode_count > 20)
1642      break;
1643 #endif
1693      switch (c)
1694      {
1695        case '+':
# Line 1653 | 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,
1661 <                                       parc, &parn,
1662 <                                       parv, &errors, alevel, dir, c,
1663 <                                       ModeTable[table_position].d,
1664 <                                       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)