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 9788 by michael, Sun Dec 6 17:43:45 2020 UTC vs.
Revision 9802 by michael, Tue Dec 8 20:50:02 2020 UTC

# Line 38 | Line 38
38  
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 */
41 >  CAPFL_STICKY = 1 << 0   /**< Cap may not be cleared once set */
42   };
43  
44   typedef int (*bqcmp)(const void *, const void *);
# Line 151 | Line 148 | 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];
151 >  char capbuf[IRCD_BUFSIZE] = "", pfx[4];
152    char cmdbuf[IRCD_BUFSIZE] = "";
153    unsigned int i, loc, len, pfx_len, clen;
154  
# Line 167 | Line 164 | send_caplist(struct Client *source_p,
164       * This is a little bit subtle, but just involves applying de
165       * Morgan's laws to the obvious check: We must display the
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.
167 >     * if both are null.
168       */
169      if (!(rem && (*rem & cap->cap)) &&
170 <        !(set && (*set & cap->cap)) &&
174 <         (rem || set || (cap->flags & CAPFL_HIDDEN)))
170 >        !(set && (*set & cap->cap)) && (rem || set))
171        continue;
172  
173      /* Build the prefix (space separator and any modifiers needed). */
# Line 181 | Line 177 | send_caplist(struct Client *source_p,
177        pfx[pfx_len++] = ' ';
178      if (rem && (*rem & cap->cap))
179        pfx[pfx_len++] = '-';
184    else
185    {
186      if (cap->flags & CAPFL_PROTO)
187        pfx[pfx_len++] = '~';
188      if (cap->flags & CAPFL_STICKY)
189        pfx[pfx_len++] = '=';
190    }
180  
181      pfx[pfx_len] = '\0';
182  
# Line 208 | Line 197 | send_caplist(struct Client *source_p,
197   }
198  
199   static void
200 < cap_ls(struct Client *source_p, const char *caplist)
200 > cap_ls(struct Client *source_p, const char *arg)
201   {
202    if (IsUnknown(source_p))  /* Registration hasn't completed; suspend it... */
203      source_p->connection->registration |= REG_NEED_CAP;
204  
205 +  if (arg && atoi(arg) >= 302)
206 +    AddFlag(source_p, FLAGS_CAP302);
207 +
208    send_caplist(source_p, NULL, NULL, "LS");  /* Send list of capabilities */
209   }
210  
211   static void
212 < cap_req(struct Client *source_p, const char *caplist)
212 > cap_req(struct Client *source_p, const char *arg)
213   {
222  const char *cl = caplist;
223  struct capabilities *cap = NULL;
214    unsigned int set = 0, rem = 0;
215 <  unsigned int cs = source_p->connection->cap_client; /* capability set */
226 <  unsigned int as = source_p->connection->cap_active; /* active set */
215 >  unsigned int cs = source_p->connection->cap;  /* Enabled capabilities */
216    int neg = 0;
217  
218    if (IsUnknown(source_p))  /* Registration hasn't completed; suspend it... */
219      source_p->connection->registration |= REG_NEED_CAP;
220  
221 <  while (cl) {  /* Walk through the capabilities list... */
222 <    if (!(cap = find_cap(&cl, &neg))  /* Look up capability... */
223 <        || (!neg && (cap->flags & CAPFL_PROHIBIT))  /* Is it prohibited? */
224 <        || (neg && (cap->flags & CAPFL_STICKY))) {  /* Is it sticky? */
221 >  /* Walk through the capabilities list... */
222 >  for (const char *cl = arg; cl; )
223 >  {
224 >    /* Look up capability... */
225 >    const struct capabilities *cap = find_cap(&cl, &neg);
226 >    if (cap == NULL ||
227 >        (neg && (cap->flags & CAPFL_STICKY)))
228 >    {
229        sendto_one(source_p, ":%s CAP %s NAK :%s", me.name,
230 <                 source_p->name[0] ? source_p->name : "*", caplist);
230 >                 source_p->name[0] ? source_p->name : "*", arg);
231        return;  /* Can't complete requested op... */
232      }
233  
# Line 244 | Line 237 | cap_req(struct Client *source_p, const c
237        rem |=  cap->cap;
238        set &= ~cap->cap;
239        cs  &= ~cap->cap;
247
248      if (!(cap->flags & CAPFL_PROTO))
249        as &= ~cap->cap;
240      }
241      else
242      {
243        rem &= ~cap->cap;
244        set |=  cap->cap;
245        cs  |=  cap->cap;
256
257      if (!(cap->flags & CAPFL_PROTO))
258        as |= cap->cap;
246      }
247    }
248  
249    /* Notify client of accepted changes and copy over results. */
250    send_caplist(source_p, &set, &rem, "ACK");
251  
252 <  source_p->connection->cap_client = cs;
266 <  source_p->connection->cap_active = as;
252 >  source_p->connection->cap = cs;
253   }
254  
255   static void
256 < cap_end(struct Client *source_p, const char *caplist)
256 > cap_end(struct Client *source_p, const char *arg)
257   {
258    if (!IsUnknown(source_p))  /* Registration has completed... */
259      return;  /* So just ignore the message... */
# Line 281 | Line 267 | cap_end(struct Client *source_p, const c
267   }
268  
269   static void
270 < cap_list(struct Client *source_p, const char *caplist)
270 > cap_list(struct Client *source_p, const char *arg)
271   {
272    /* Send the list of the client's capabilities */
273 <  send_caplist(source_p, &source_p->connection->cap_client, NULL, "LIST");
273 >  send_caplist(source_p, &source_p->connection->cap, NULL, "LIST");
274   }
275  
276   static struct subcmd

Diff Legend

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