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 5347 by michael, Sun Jan 11 12:42:20 2015 UTC vs.
Revision 9101 by michael, Wed Jan 1 09:58:45 2020 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-2015 ircd-hybrid development team
5 > *  Copyright (c) 2006-2020 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 36 | Line 36
36   #include "irc_string.h"
37  
38  
39 < #define CAPFL_HIDDEN    0x0001  /**< Do not advertize this capability */
40 < #define CAPFL_PROHIBIT  0x0002  /**< Client may not set this capability */
41 < #define CAPFL_PROTO     0x0004  /**< Cap must be acknowledged by client */
42 < #define CAPFL_STICKY    0x0008  /**< Cap may not be cleared once set */
39 > enum
40 > {
41 >  CAPFL_HIDDEN    = 1 << 0,  /**< Do not advertize this capability */
42 >  CAPFL_PROHIBIT  = 1 << 1,  /**< Client may not set this capability */
43 >  CAPFL_PROTO     = 1 << 2,  /**< Cap must be acknowledged by client */
44 >  CAPFL_STICKY    = 1 << 3   /**< Cap may not be cleared once set */
45 > };
46  
47   typedef int (*bqcmp)(const void *, const void *);
48  
# Line 55 | Line 58 | static struct capabilities
58    _CAP(CAP_UHNAMES, 0, "userhost-in-names"),
59    _CAP(CAP_MULTI_PREFIX, 0, "multi-prefix"),
60    _CAP(CAP_AWAY_NOTIFY, 0, "away-notify"),
61 <  _CAP(CAP_EXTENDED_JOIN, 0, "extended-join")
61 >  _CAP(CAP_EXTENDED_JOIN, 0, "extended-join"),
62 >  _CAP(CAP_ACCOUNT_NOTIFY, 0, "account-notify"),
63 >  _CAP(CAP_INVITE_NOTIFY, 0, "invite-notify"),
64 >  _CAP(CAP_CHGHOST, 0, "chghost")
65   #undef _CAP
66   };
67  
# Line 140 | Line 146 | find_cap(const char **caplist_p, int *ne
146   * @param[in] rem Capabalities to show as removed (with no other modifier).
147   * @param[in] subcmd Name of capability subcommand.
148   */
149 < static int
149 > static void
150   send_caplist(struct Client *source_p,
151               const unsigned int *const set,
152               const unsigned int *const rem, const char *subcmd)
# Line 199 | Line 205 | send_caplist(struct Client *source_p,
205    }
206  
207    sendto_one(source_p, "%s:%s", cmdbuf, capbuf);
202
203  return 0;  /* Convenience return */
208   }
209  
210 < static int
210 > static void
211   cap_ls(struct Client *source_p, const char *caplist)
212   {
213    if (IsUnknown(source_p))  /* Registration hasn't completed; suspend it... */
214      source_p->connection->registration |= REG_NEED_CAP;
215  
216 <  return send_caplist(source_p, NULL, NULL, "LS");  /* Send list of capabilities */
216 >  send_caplist(source_p, NULL, NULL, "LS");  /* Send list of capabilities */
217   }
218  
219 < static int
219 > static void
220   cap_req(struct Client *source_p, const char *caplist)
221   {
222    const char *cl = caplist;
# Line 231 | Line 235 | cap_req(struct Client *source_p, const c
235          || (neg && (cap->flags & CAPFL_STICKY))) {  /* Is it sticky? */
236        sendto_one(source_p, ":%s CAP %s NAK :%s", me.name,
237                   source_p->name[0] ? source_p->name : "*", caplist);
238 <      return 0;  /* Can't complete requested op... */
238 >      return;  /* Can't complete requested op... */
239      }
240  
241      if (neg)
# Line 260 | Line 264 | cap_req(struct Client *source_p, const c
264  
265    source_p->connection->cap_client = cs;
266    source_p->connection->cap_active = as;
263
264  return 0;
267   }
268  
269 < static int
269 > static void
270   cap_ack(struct Client *source_p, const char *caplist)
271   {
272    const char *cl = caplist;
# Line 284 | Line 286 | cap_ack(struct Client *source_p, const c
286                !(source_p->connection->cap_client & cap->cap)))  /* uh... */
287        continue;
288  
289 <    if (neg)  /* Set or clear the active capability... */
289 >    /* Set or clear the active capability... */
290 >    if (neg)
291 >    {
292 >      if (cap->flags & CAPFL_STICKY)
293 >        continue;  /* but don't clear sticky capabilities */
294 >
295        source_p->connection->cap_active &= ~cap->cap;
296 +    }
297      else
298 +    {
299 +      if (cap->flags & CAPFL_PROHIBIT)
300 +        continue;  /* and don't set prohibited ones */
301 +
302        source_p->connection->cap_active |=  cap->cap;
303 +    }
304    }
292
293  return 0;
305   }
306  
307 < static int
307 > static void
308   cap_clear(struct Client *source_p, const char *caplist)
309   {
299  struct capabilities *cap = NULL;
310    unsigned int cleared = 0;
311  
312    for (unsigned int ii = 0; ii < CAPAB_LIST_LEN; ++ii)
313    {
314 <    cap = &capab_list[ii];
314 >    const struct capabilities *cap = &capab_list[ii];
315  
316      /* Only clear active non-sticky capabilities. */
317      if (!(source_p->connection->cap_client & cap->cap) || (cap->flags & CAPFL_STICKY))
# Line 314 | Line 324 | cap_clear(struct Client *source_p, const
324        source_p->connection->cap_active &= ~cap->cap;
325    }
326  
327 <  return send_caplist(source_p, NULL, &cleared, "ACK");
327 >  send_caplist(source_p, NULL, &cleared, "ACK");
328   }
329  
330 < static int
330 > static void
331   cap_end(struct Client *source_p, const char *caplist)
332   {
333    if (!IsUnknown(source_p))  /* Registration has completed... */
334 <    return 0;  /* So just ignore the message... */
334 >    return;  /* So just ignore the message... */
335  
336    /* Capability negotiation is now done... */
337    source_p->connection->registration &= ~REG_NEED_CAP;
338  
339    /* If client is now done... */
340 <  if (!source_p->connection->registration)
331 <  {
340 >  if (source_p->connection->registration == 0)
341      register_local_user(source_p);
333    return 0;
334  }
335
336  return 0;  /* Can't do registration yet... */
342   }
343  
344 < static int
344 > static void
345   cap_list(struct Client *source_p, const char *caplist)
346   {
347    /* Send the list of the client's capabilities */
348 <  return send_caplist(source_p, &source_p->connection->cap_client, NULL, "LIST");
348 >  send_caplist(source_p, &source_p->connection->cap_client, NULL, "LIST");
349   }
350  
351   static struct subcmd
352   {
353    const char *cmd;
354 <  int (*proc)(struct Client *, const char *);
354 >  void (*proc)(struct Client *, const char *);
355   } cmdlist[] = {
356    { "ACK",   cap_ack   },
357    { "CLEAR", cap_clear },
# Line 375 | Line 380 | subcmd_search(const char *cmd, const str
380   *      - parv[1] = CAP subcommand
381   *      - parv[2] = space-separated list of capabilities
382   */
383 < static int
383 > static void
384   m_cap(struct Client *source_p, int parc, char *parv[])
385   {
386    const char *subcmd = NULL, *caplist = NULL;
387    struct subcmd *cmd = NULL;
388  
389    if (EmptyString(parv[1]))  /* A subcommand is required */
390 <    return 0;
390 >    return;
391  
392    subcmd = parv[1];
393  
# Line 395 | Line 400 | m_cap(struct Client *source_p, int parc,
400                        sizeof(struct subcmd), (bqcmp)subcmd_search)))
401    {
402      sendto_one_numeric(source_p, &me, ERR_INVALIDCAPCMD, subcmd);
403 <    return 0;
403 >    return;
404    }
405  
406    /* Then execute it... */
407    if (cmd->proc)
408      (cmd->proc)(source_p, caplist);
404  return 0;
409   }
410  
411   static struct Message cap_msgtab =
412   {
413 <  "CAP", NULL, 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
414 <  { m_cap, m_cap, m_ignore, m_ignore, m_cap, m_ignore }
413 >  .cmd = "CAP",
414 >  .args_min = 2,
415 >  .args_max = MAXPARA,
416 >  .handlers[UNREGISTERED_HANDLER] = m_cap,
417 >  .handlers[CLIENT_HANDLER] = m_cap,
418 >  .handlers[SERVER_HANDLER] = m_ignore,
419 >  .handlers[ENCAP_HANDLER] = m_ignore,
420 >  .handlers[OPER_HANDLER] = m_cap
421   };
422  
423   static void
# Line 426 | Line 436 | module_exit(void)
436  
437   struct module module_entry =
438   {
429  .node    = { NULL, NULL, NULL },
430  .name    = NULL,
439    .version = "$Revision$",
432  .handle  = NULL,
440    .modinit = module_init,
441    .modexit = module_exit,
435  .flags   = 0
442   };

Diff Legend

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