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

Comparing ircd-hybrid/trunk/modules/m_cap.c (file contents):
Revision 4792 by michael, Tue Oct 28 12:44:43 2014 UTC vs.
Revision 7924 by michael, Sat Dec 31 13:57:08 2016 UTC

# Line 2 | Line 2
2   *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4   *  Copyright (c) 2004 Kevin L. Mitchell <klmitch@mit.edu>
5 < *  Copyright (c) 2006-2014 ircd-hybrid development team
5 > *  Copyright (c) 2006-2017 ircd-hybrid development team
6   *
7   *  This program is free software; you can redistribute it and/or modify
8   *  it under the terms of the GNU General Public License as published by
# Line 27 | Line 27
27  
28   #include "stdinc.h"
29   #include "client.h"
30 #include "hash.h"
30   #include "ircd.h"
31   #include "numeric.h"
32   #include "user.h"
# Line 56 | Line 55 | static struct capabilities
55    _CAP(CAP_UHNAMES, 0, "userhost-in-names"),
56    _CAP(CAP_MULTI_PREFIX, 0, "multi-prefix"),
57    _CAP(CAP_AWAY_NOTIFY, 0, "away-notify"),
58 <  _CAP(CAP_EXTENDED_JOIN, 0, "extended-join")
58 >  _CAP(CAP_EXTENDED_JOIN, 0, "extended-join"),
59 >  _CAP(CAP_ACCOUNT_NOTIFY, 0, "account-notify"),
60 >  _CAP(CAP_INVITE_NOTIFY, 0, "invite-notify"),
61 >  _CAP(CAP_CHGHOST, 0, "chghost")
62   #undef _CAP
63   };
64  
# Line 77 | Line 79 | capab_search(const char *key, const stru
79      if (*key++ == '\0')  /* Hit the end, all right... */
80        return 0;
81      else  /* OK, let's move on... */
82 <      rb++;
82 >      ++rb;
83  
84    /*
85     * If the character they differ on happens to be a space, and it happens
# Line 142 | Line 144 | find_cap(const char **caplist_p, int *ne
144   * @param[in] subcmd Name of capability subcommand.
145   */
146   static int
147 < send_caplist(struct Client *source_p, unsigned int set,
148 <             unsigned int rem, const char *subcmd)
147 > send_caplist(struct Client *source_p,
148 >             const unsigned int *const set,
149 >             const unsigned int *const rem, const char *subcmd)
150   {
151    char capbuf[IRCD_BUFSIZE] = "", pfx[16];
152    char cmdbuf[IRCD_BUFSIZE] = "";
153 <  unsigned int i, loc, len, flags, pfx_len, clen;
153 >  unsigned int i, loc, len, pfx_len, clen;
154  
155    /* Set up the buffer for the final LS message... */
156    clen = snprintf(cmdbuf, sizeof(capbuf), ":%s CAP %s %s ", me.name,
# Line 155 | Line 158 | send_caplist(struct Client *source_p, un
158  
159    for (i = 0, loc = 0; i < CAPAB_LIST_LEN; ++i)
160    {
161 <    flags = capab_list[i].flags;
161 >    const struct capabilities *cap = &capab_list[i];
162  
163      /*
164       * This is a little bit subtle, but just involves applying de
# Line 163 | Line 166 | send_caplist(struct Client *source_p, un
166       * capability if (and only if) it is set in \a rem or \a set, or
167       * if both are null and the capability is hidden.
168       */
169 <    if (!(rem && (rem & capab_list[i].cap)) &&
170 <        !(set && (set & capab_list[i].cap)) &&
171 <         (rem || set || (flags & CAPFL_HIDDEN)))
169 >    if (!(rem && (*rem & cap->cap)) &&
170 >        !(set && (*set & cap->cap)) &&
171 >         (rem || set || (cap->flags & CAPFL_HIDDEN)))
172        continue;
173  
174      /* Build the prefix (space separator and any modifiers needed). */
# Line 173 | Line 176 | send_caplist(struct Client *source_p, un
176  
177      if (loc)
178        pfx[pfx_len++] = ' ';
179 <    if (rem && (rem & capab_list[i].cap))
179 >    if (rem && (*rem & cap->cap))
180        pfx[pfx_len++] = '-';
181      else
182      {
183 <      if (flags & CAPFL_PROTO)
183 >      if (cap->flags & CAPFL_PROTO)
184          pfx[pfx_len++] = '~';
185 <      if (flags & CAPFL_STICKY)
185 >      if (cap->flags & CAPFL_STICKY)
186          pfx[pfx_len++] = '=';
187      }
188  
189      pfx[pfx_len] = '\0';
190  
191 <    len = capab_list[i].namelen + pfx_len;  /* How much we'd add... */
191 >    len = cap->namelen + pfx_len;  /* How much we'd add... */
192  
193      if (sizeof(capbuf) < (clen + loc + len + 15))
194      {
# Line 195 | Line 198 | send_caplist(struct Client *source_p, un
198      }
199  
200      loc += snprintf(capbuf + loc, sizeof(capbuf) - loc,
201 <                    "%s%s", pfx, capab_list[i].name);
201 >                    "%s%s", pfx, cap->name);
202    }
203  
204    sendto_one(source_p, "%s:%s", cmdbuf, capbuf);
# Line 209 | Line 212 | cap_ls(struct Client *source_p, const ch
212    if (IsUnknown(source_p))  /* Registration hasn't completed; suspend it... */
213      source_p->connection->registration |= REG_NEED_CAP;
214  
215 <  return send_caplist(source_p, 0, 0, "LS");  /* Send list of capabilities */
215 >  return send_caplist(source_p, NULL, NULL, "LS");  /* Send list of capabilities */
216   }
217  
218   static int
# Line 256 | Line 259 | cap_req(struct Client *source_p, const c
259    }
260  
261    /* Notify client of accepted changes and copy over results. */
262 <  send_caplist(source_p, set, rem, "ACK");
262 >  send_caplist(source_p, &set, &rem, "ACK");
263  
264    source_p->connection->cap_client = cs;
265    source_p->connection->cap_active = as;
# Line 280 | Line 283 | cap_ack(struct Client *source_p, const c
283    {
284      /* Walk through the capabilities list... */
285      if (!(cap = find_cap(&cl, &neg)) ||  /* Look up capability... */
286 <        (neg ? (source_p->connection->cap_active & cap->cap) :
287 <              !(source_p->connection->cap_active & cap->cap)))  /* uh... */
286 >        (neg ? (source_p->connection->cap_client & cap->cap) :
287 >              !(source_p->connection->cap_client & cap->cap)))  /* uh... */
288        continue;
289  
290 <    if (neg)  /* Set or clear the active capability... */
290 >    /* Set or clear the active capability... */
291 >    if (neg)
292 >    {
293 >      if (cap->flags & CAPFL_STICKY)
294 >        continue;  /* but don't clear sticky capabilities */
295 >
296        source_p->connection->cap_active &= ~cap->cap;
297 +    }
298      else
299 +    {
300 +      if (cap->flags & CAPFL_PROHIBIT)
301 +        continue;  /* and don't set prohibited ones */
302 +
303        source_p->connection->cap_active |=  cap->cap;
304 +    }
305    }
306  
307    return 0;
# Line 296 | Line 310 | cap_ack(struct Client *source_p, const c
310   static int
311   cap_clear(struct Client *source_p, const char *caplist)
312   {
299  struct capabilities *cap = NULL;
313    unsigned int cleared = 0;
314  
315    for (unsigned int ii = 0; ii < CAPAB_LIST_LEN; ++ii)
316    {
317 <    cap = &capab_list[ii];
317 >    const struct capabilities *cap = &capab_list[ii];
318  
319      /* Only clear active non-sticky capabilities. */
320 <    if (!(source_p->connection->cap_active & cap->cap) || (cap->flags & CAPFL_STICKY))
320 >    if (!(source_p->connection->cap_client & cap->cap) || (cap->flags & CAPFL_STICKY))
321        continue;
322  
323      cleared |= cap->cap;
# Line 314 | Line 327 | cap_clear(struct Client *source_p, const
327        source_p->connection->cap_active &= ~cap->cap;
328    }
329  
330 <  return send_caplist(source_p, 0, cleared, "ACK");
330 >  return send_caplist(source_p, NULL, &cleared, "ACK");
331   }
332  
333   static int
# Line 340 | Line 353 | static int
353   cap_list(struct Client *source_p, const char *caplist)
354   {
355    /* Send the list of the client's capabilities */
356 <  return send_caplist(source_p, source_p->connection->cap_client, 0, "LIST");
356 >  return send_caplist(source_p, &source_p->connection->cap_client, NULL, "LIST");
357   }
358  
359   static struct subcmd
# Line 406 | Line 419 | m_cap(struct Client *source_p, int parc,
419  
420   static struct Message cap_msgtab =
421   {
422 <  "CAP", NULL, 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
423 <  { m_cap, m_cap, m_ignore, m_ignore, m_cap, m_ignore }
422 >  .cmd = "CAP",
423 >  .args_min = 2,
424 >  .args_max = MAXPARA,
425 >  .handlers[UNREGISTERED_HANDLER] = m_cap,
426 >  .handlers[CLIENT_HANDLER] = m_cap,
427 >  .handlers[SERVER_HANDLER] = m_ignore,
428 >  .handlers[ENCAP_HANDLER] = m_ignore,
429 >  .handlers[OPER_HANDLER] = m_cap
430   };
431  
432   static void
# Line 426 | Line 445 | module_exit(void)
445  
446   struct module module_entry =
447   {
429  .node    = { NULL, NULL, NULL },
430  .name    = NULL,
448    .version = "$Revision$",
432  .handle  = NULL,
449    .modinit = module_init,
450    .modexit = module_exit,
435  .flags   = 0
451   };

Diff Legend

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