This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Undernet IRC Server Source Code.".

The branch, u2_10_12_branch has been updated
       via  ec0e3eb1c47adda360f486219b5c99484daaa377 (commit)
       via  cd6e2e4180f122fd203a0d593b2ab1fdb3c24d15 (commit)
       via  dfd9afa60228820c99d407fbc061173bf605116d (commit)
       via  6f0fc9516491e65d38a6546dc78ee40a9963e079 (commit)
       via  2e93875f800a6a24e894e9ce7d457fff5609516b (commit)
      from  3525ba0c3306b7cf6c551467df5329a469b40f41 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit ec0e3eb1c47adda360f486219b5c99484daaa377
Merge: 3525ba0c cd6e2e41
Author: Michael Poole <[email protected]>
Date:   Sun Apr 6 13:40:31 2025 -0400

    Merge pull request #48 from MrIron-no/capset
    
    Fixes to cap handling

commit cd6e2e4180f122fd203a0d593b2ab1fdb3c24d15
Author: Erik Tørrissen <[email protected]>
Date:   Mon Mar 3 22:08:47 2025 +0100

    Minor fix.

diff --git a/ircd/channel.c b/ircd/channel.c
index 39f2d7e0..16eacc36 100644
--- a/ircd/channel.c
+++ b/ircd/channel.c
@@ -3652,6 +3652,9 @@ void RevealDelayedJoin(struct Membership *member)
 {
   ClearDelayedJoin(member);
   sendjointo_channel_butserv(member->user, member->channel, 0, 0);
+  if (cli_user(member->user)->away)
+    sendcmdto_capflag_channel_butserv_butone(member->user, CMD_AWAY, 
member->channel,
+      NULL, 0, CAP_AWAYNOTIFY, 0, ":%s", cli_user(member->user)->away);
   CheckDelayedJoins(member->channel);
 }
 
diff --git a/ircd/m_account.c b/ircd/m_account.c
index 05ddf8d9..a55f6944 100644
--- a/ircd/m_account.c
+++ b/ircd/m_account.c
@@ -153,10 +153,9 @@ int ms_account(struct Client* cptr, struct Client* sptr, 
int parc,
     }
 
     ircd_strncpy(cli_user(acptr)->account, parv[2], ACCOUNTLEN);
-    hide_hostmask(acptr, FLAG_ACCOUNT);
-
     sendcmdto_capflag_common_channels_butone(acptr, CMD_ACCOUNT, NULL, 
CAP_ACCOUNTNOTIFY,
                           0, "%s", cli_user(acptr)->account);
+    hide_hostmask(acptr, FLAG_ACCOUNT);
   }
 
   if (parc > 4) {
diff --git a/ircd/m_burst.c b/ircd/m_burst.c
index a226c71b..be9eaa26 100644
--- a/ircd/m_burst.c
+++ b/ircd/m_burst.c
@@ -543,8 +543,12 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int 
parc, char *parv[])
          if (!(member = find_member_link(chptr, acptr)))
          {
            add_user_to_channel(chptr, acptr, current_mode, oplevel);
-           if (!(current_mode & CHFL_DELAYED))
+           if (!(current_mode & CHFL_DELAYED)) {
              sendjointo_channel_butserv(acptr, chptr, 0, 0);
+              if (cli_user(acptr)->away)
+                sendcmdto_capflag_channel_butserv_butone(acptr, CMD_AWAY, 
chptr,
+                  NULL, 0, CAP_AWAYNOTIFY, 0, ":%s", cli_user(acptr)->away);
+              }
          }
          else
          {
diff --git a/ircd/m_cap.c b/ircd/m_cap.c
index 2cc0159f..1709cfd1 100644
--- a/ircd/m_cap.c
+++ b/ircd/m_cap.c
@@ -45,7 +45,7 @@
 typedef int (*bqcmp)(const void *, const void *);
 
 static struct capabilities {
-  enum Capab cap;
+  enum CapabBits cap;
   char *capstr;
   unsigned int config;
   unsigned long flags;
@@ -53,7 +53,7 @@ static struct capabilities {
   int namelen;
 } capab_list[] = {
 #define _CAP(cap, config, flags, name)      \
-       { E_CAP_ ## cap, #cap, (config), (flags), (name), sizeof(name) - 1 }
+       { CAP_ ## cap, #cap, (config), (flags), (name), sizeof(name) - 1 }
   CAPLIST
 #undef _CAP
 };
@@ -151,6 +151,10 @@ send_caplist(struct Client *sptr, capset_t set,
   for (i = 0, loc = 0; i < CAPAB_LIST_LEN; i++) {
     flags = capab_list[i].flags;
 
+    /* If the client has no capabilities set, and this is the LIST subcmd, 
break. */
+    if (!set && !strcmp(subcmd, "LIST"))
+      break;
+
     /* Check if the capability is enabled in features() */
     if (!feature_bool(capab_list[i].config))
       continue;
@@ -217,8 +221,6 @@ cap_req(struct Client *sptr, const char *caplist)
   if (IsUserPort(sptr)) /* registration hasn't completed; suspend it... */
     auth_cap_start(cli_auth(sptr));
 
-  memset(&set, 0, sizeof(set));
-  memset(&rem, 0, sizeof(rem));
   while (cl) { /* walk through the capabilities list... */
     if (!(cap = find_cap(&cl, &neg)) /* look up capability... */
         || !feature_bool(cap->config) /* is it deactivated in config? */
diff --git a/ircd/send.c b/ircd/send.c
index e3a5bbbf..9dbd2921 100644
--- a/ircd/send.c
+++ b/ircd/send.c
@@ -559,8 +559,8 @@ void sendcmdto_capflag_common_channels_butone(struct Client 
*from, const char *c
           && -1 < cli_fd(cli_from(member->user))
           && member->user != one
           && cli_sentalong(member->user) != sentalong_marker
-          && CapHas(cli_active(member->user), require)
-          && !CapHas(cli_active(member->user), forbid))
+          && (require == 0 || CapHas(cli_active(member->user), require))
+          && (forbid == 0 || !CapHas(cli_active(member->user), forbid)))
       {
           cli_sentalong(member->user) = sentalong_marker;
           send_buffer(member->user, mb, 0);
@@ -570,8 +570,8 @@ void sendcmdto_capflag_common_channels_butone(struct Client 
*from, const char *c
 
   if (MyConnect(from)
       && from != one
-      && (require == _CAP_LAST_CAP || CapHas(cli_active(from), require))
-      && (forbid == _CAP_LAST_CAP || !CapHas(cli_active(from), forbid)))
+      && (require == 0 || CapHas(cli_active(from), require))
+      && (forbid == 0 || !CapHas(cli_active(from), forbid)))
     send_buffer(from, mb, 0);
 
   msgq_clean(mb);
@@ -613,8 +613,8 @@ void sendcmdto_capflag_channel_butserv_butone(struct Client 
*from, const char *c
         || (skip & SKIP_DEAF && IsDeaf(member->user))
         || (skip & SKIP_NONOPS && !IsChanOp(member))
         || (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member))
-        || !CapHas(cli_active(member->user), require)
-        || CapHas(cli_active(member->user), forbid))
+        || (require && !CapHas(cli_active(member->user), require))
+        || (forbid && CapHas(cli_active(member->user), forbid)))
         continue;
 
     send_buffer(member->user, mb, 0);
@@ -651,10 +651,10 @@ void sendjointo_one(struct Client *from,
                    struct Client *one)
 {
   if (CapHas(cli_active(one), CAP_EXTJOIN))
-    sendcmdto_one(one, CMD_JOIN, from, "%H %s :%s", chptr,
+    sendcmdto_one(from, CMD_JOIN, one, "%H %s :%s", chptr,
       IsAccount(from) ? cli_account(from) : "*", cli_info(from));
   else
-    sendcmdto_one(one, CMD_JOIN, from, "%H", chptr);
+    sendcmdto_one(from, CMD_JOIN, one, "%H", chptr);
 }
 
 /** Send a (prefixed) command to all local users on a channel.
commit dfd9afa60228820c99d407fbc061173bf605116d
Author: Michael Poole <[email protected]>
Date:   Sun Mar 2 21:35:21 2025 -0500

    Consistently honor CAP_EXTJOIN
    
    Also send AWAY to CAP_AWAYNOTIFY clients when hiding a client's hostmask.

diff --git a/include/send.h b/include/send.h
index 6f5b6284..0bbbda83 100644
--- a/include/send.h
+++ b/include/send.h
@@ -13,6 +13,10 @@
 #define INCLUDED_time_h
 #endif
 
+#ifndef INCLUDED_client_h
+#include "client.h" /* capset_t */
+#endif
+
 struct Channel;
 struct Client;
 struct DBuf;
@@ -67,15 +71,16 @@ extern void sendcmdto_capflag_common_channels_butone(struct 
Client *from,
                                                     const char *cmd,
                                                     const char *tok,
                                                     struct Client *one,
-                                                    int require,
-                                                    int forbid,
+                                                    capset_t require,
+                                                    capset_t forbid,
                                                     const char *pattern, ...);
 
 /* Send command to all channel users on this server matching or not matching a 
capability flag */
 void sendcmdto_capflag_channel_butserv_butone(struct Client *from, const char 
*cmd,
                                              const char *tok, struct Channel 
*to,
                                              struct Client *one, unsigned int 
skip,
-                                             int require, int forbid, const 
char *pattern, ...);
+                                             capset_t require, capset_t forbid,
+                                             const char *pattern, ...);
 
 /* Send command to all channel users on this server */
 extern void sendcmdto_channel_butserv_butone(struct Client *from,
@@ -101,6 +106,18 @@ extern void sendcmdto_channel_butone(struct Client *from, 
const char *cmd,
                                     struct Client *one, unsigned int skip,
                                     const char *pattern, ...);
 
+
+/* Send JOIN to all local channel users matching or not matching capability 
flags */
+extern void sendjointo_channel_butserv(struct Client *from,
+                                      struct Channel *chptr,
+                                      capset_t require,
+                                      capset_t forbid);
+
+/* Send JOIN to a single user */
+extern void sendjointo_one(struct Client *from,
+                          struct Channel *chptr,
+                          struct Client *one);
+
 #define SKIP_DEAF      0x01    /**< skip users that are +d */
 #define SKIP_BURST     0x02    /**< skip users that are bursting */
 #define SKIP_NONOPS    0x04    /**< skip users that aren't chanops */
diff --git a/ircd/channel.c b/ircd/channel.c
index 2befe56f..39f2d7e0 100644
--- a/ircd/channel.c
+++ b/ircd/channel.c
@@ -3556,12 +3556,7 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, 
unsigned int flags)
 
     if (!((chan->mode.mode & MODE_DELJOINS) && !(flags & 
CHFL_VOICED_OR_OPPED))) {
       /* Send the notification to the channel */
-      sendcmdto_capflag_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, 
chan, NULL, 0,
-        0, CAP_EXTJOIN, "%H", chan);
-      sendcmdto_capflag_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, 
chan, NULL, 0,
-        CAP_EXTJOIN, 0, "%H %s :%s", chan,
-        IsAccount(jbuf->jb_source) ? cli_account(jbuf->jb_source) : "*",
-        cli_info(jbuf->jb_source));
+      sendjointo_channel_butserv(jbuf->jb_source, chan, 0, 0);
       if (cli_user(jbuf->jb_source)->away)
         sendcmdto_capflag_common_channels_butone(jbuf->jb_source, CMD_AWAY, 
jbuf->jb_connect,
           CAP_AWAYNOTIFY, 0, ":%s", cli_user(jbuf->jb_source)->away);
@@ -3572,7 +3567,7 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, 
unsigned int flags)
                                          CMD_MODE, chan, NULL, 0, "%H +o %C",
                                         chan, jbuf->jb_source);
     } else if (MyUser(jbuf->jb_source))
-      sendcmdto_one(jbuf->jb_source, CMD_JOIN, jbuf->jb_source, ":%H", chan);
+      sendjointo_one(jbuf->jb_source, chan, jbuf->jb_source);
   }
 
   if (jbuf->jb_type == JOINBUF_TYPE_PARTALL ||
@@ -3656,13 +3651,7 @@ int IsInvited(struct Client* cptr, const void* chptr)
 void RevealDelayedJoin(struct Membership *member)
 {
   ClearDelayedJoin(member);
-  sendcmdto_capflag_channel_butserv_butone(member->user, CMD_JOIN, 
member->channel, NULL, 0,
-        0, CAP_EXTJOIN, "%H", member->channel);
-  sendcmdto_capflag_channel_butserv_butone(member->user, CMD_JOIN, 
member->channel, NULL, 0,
-        CAP_EXTJOIN, 0, "%H %s :%s", member->channel,
-        IsAccount(member->user) ? cli_account(member->user) : "*",
-        cli_info(member->user));
-
+  sendjointo_channel_butserv(member->user, member->channel, 0, 0);
   CheckDelayedJoins(member->channel);
 }
 
diff --git a/ircd/m_burst.c b/ircd/m_burst.c
index 380f92ca..a226c71b 100644
--- a/ircd/m_burst.c
+++ b/ircd/m_burst.c
@@ -543,8 +543,8 @@ int ms_burst(struct Client *cptr, struct Client *sptr, int 
parc, char *parv[])
          if (!(member = find_member_link(chptr, acptr)))
          {
            add_user_to_channel(chptr, acptr, current_mode, oplevel);
-            if (!(current_mode & CHFL_DELAYED))
-              sendcmdto_channel_butserv_butone(acptr, CMD_JOIN, chptr, NULL, 
0, "%H", chptr);
+           if (!(current_mode & CHFL_DELAYED))
+             sendjointo_channel_butserv(acptr, chptr, 0, 0);
          }
          else
          {
diff --git a/ircd/m_destruct.c b/ircd/m_destruct.c
index d76f51d8..032237a2 100644
--- a/ircd/m_destruct.c
+++ b/ircd/m_destruct.c
@@ -153,14 +153,7 @@ int ms_destruct(struct Client* cptr, struct Client* sptr, 
int parc, char* parv[]
 
     /* Next, send JOINs for all members. */
     for (member = chptr->members; member; member = member->next_member)
-    {
-      if (CapHas(cli_active(member->user), CAP_EXTJOIN))
-        sendcmdto_one(member->user, CMD_JOIN, cptr,
-        "%H %s :%s", chptr, IsAccount(cptr) ? cli_account(cptr) : "*",
-        cli_info(cptr));
-      else
-        sendcmdto_one(member->user, CMD_JOIN, cptr, "%H", chptr);
-    }
+      sendjointo_one(member->user, chptr, cptr);
 
     /* Build MODE strings. We use MODEBUF_DEST_BOUNCE with MODE_DEL to assure
        that the resulting MODEs are only sent upstream. */
diff --git a/ircd/m_kick.c b/ircd/m_kick.c
index c789e372..8fd358a7 100644
--- a/ircd/m_kick.c
+++ b/ircd/m_kick.c
@@ -164,7 +164,7 @@ int m_kick(struct Client *cptr, struct Client *sptr, int 
parc, char *parv[])
      * the kicking and the victim */
     if (MyUser(who))
       sendcmdto_one(sptr, CMD_KICK, who, "%H %C :%s", chptr, who, comment);
-    sendcmdto_one(who, CMD_JOIN, sptr, "%H", chptr);
+    sendjointo_one(who, chptr, sptr);
     sendcmdto_one(sptr, CMD_KICK, sptr, "%H %C :%s", chptr, who, comment);
     CheckDelayedJoins(chptr);
   } else
@@ -239,7 +239,7 @@ int ms_kick(struct Client *cptr, struct Client *sptr, int 
parc, char *parv[])
     sendto_opmask_butone(0, SNO_HACK2, "HACK: %C KICK %H %C %s", sptr, chptr,
                         who, comment);
 
-    sendcmdto_one(who, CMD_JOIN, cptr, "%H", chptr);
+    sendjointo_one(who, chptr, cptr);
 
     /* Reop/revoice member */
     if (IsChanOp(member) || HasVoice(member)) {
diff --git a/ircd/s_user.c b/ircd/s_user.c
index 33296dba..13c61cb1 100644
--- a/ircd/s_user.c
+++ b/ircd/s_user.c
@@ -923,8 +923,12 @@ hide_hostmask(struct Client *cptr, unsigned int flag)
       continue;
     /* Send a JOIN unless the user's join has been delayed. */
     if (!IsDelayedJoin(chan))
-      sendcmdto_capflag_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, 
cptr, 0,
-                                         0, CAP_CHGHOST, "%H", chan->channel);
+    {
+      sendjointo_channel_butserv(cptr, chan->channel, 0, CAP_CHGHOST);
+      if (cli_user(cptr)->away)
+        sendcmdto_capflag_channel_butserv_butone(cptr, CMD_AWAY, chan->channel,
+          NULL, 0, CAP_AWAYNOTIFY, CAP_CHGHOST, ":%s", cli_user(cptr)->away);
+    }
     if (IsChanOp(chan) && HasVoice(chan))
       sendcmdto_capflag_channel_butserv_butone(&his, CMD_MODE, chan->channel, 
cptr, 0,
                                        0, CAP_CHGHOST, "%H +ov %C %C", 
chan->channel, cptr,
diff --git a/ircd/send.c b/ircd/send.c
index a739cc4a..e3a5bbbf 100644
--- a/ircd/send.c
+++ b/ircd/send.c
@@ -524,7 +524,7 @@ void sendcmdto_common_channels_butone(struct Client *from, 
const char *cmd,
  */
 void sendcmdto_capflag_common_channels_butone(struct Client *from, const char 
*cmd,
                                              const char *tok, struct Client 
*one,
-                                             int require, int forbid, const 
char *pattern, ...)
+                                             capset_t require, capset_t 
forbid, const char *pattern, ...)
 {
   struct VarData vd;
   struct MsgBuf *mb;
@@ -591,7 +591,8 @@ void sendcmdto_capflag_common_channels_butone(struct Client 
*from, const char *c
 void sendcmdto_capflag_channel_butserv_butone(struct Client *from, const char 
*cmd,
                                              const char *tok, struct Channel 
*to,
                                              struct Client *one, unsigned int 
skip,
-                                             int require, int forbid, const 
char *pattern, ...)
+                                             capset_t require, capset_t forbid,
+                                             const char *pattern, ...)
 {
   struct VarData vd;
   struct MsgBuf *mb;
@@ -622,6 +623,40 @@ void sendcmdto_capflag_channel_butserv_butone(struct 
Client *from, const char *c
   msgq_clean(mb);
 }
 
+/* Send JOIN to all local channel users matching or not matching
+ * capability flags.
+ * @param[in] from Client joining the channel.
+ * @param[in] chptr Channel being joined.
+ * @param[in] require Capability mask to send this message for.
+ * @param[in] forbid Capability mask to block this message for.
+ */
+void sendjointo_channel_butserv(struct Client *from, struct Channel *chptr,
+                               capset_t require,
+                               capset_t forbid)
+{
+  sendcmdto_capflag_channel_butserv_butone(from, CMD_JOIN, chptr, NULL,
+    0, require | CAP_EXTJOIN, forbid, "%H %s :%s", chptr,
+    IsAccount(from) ? cli_account(from) : "*", cli_info(from));
+  sendcmdto_capflag_channel_butserv_butone(from, CMD_JOIN, chptr, NULL,
+    0, require, forbid | CAP_EXTJOIN, "%H", chptr);
+}
+
+/* Send JOIN to a single user.
+ * @param[in] from Client joining the channel.
+ * @param[in] chptr Channel being joined.
+ * @param[in] one Client to send the message to.
+ */
+void sendjointo_one(struct Client *from,
+                   struct Channel *chptr,
+                   struct Client *one)
+{
+  if (CapHas(cli_active(one), CAP_EXTJOIN))
+    sendcmdto_one(one, CMD_JOIN, from, "%H %s :%s", chptr,
+      IsAccount(from) ? cli_account(from) : "*", cli_info(from));
+  else
+    sendcmdto_one(one, CMD_JOIN, from, "%H", chptr);
+}
+
 /** Send a (prefixed) command to all local users on a channel.
  * @param[in] from Client originating the command.
  * @param[in] cmd Long name of command.
commit 6f0fc9516491e65d38a6546dc78ee40a9963e079
Author: Michael Poole <[email protected]>
Date:   Sun Mar 2 17:37:49 2025 -0500

    Convert struct CapSet to a bare bitfield.
    
    This allows using 0 in place of _CAP_LAST_CAP in sendcmdto_capflag_*(),
    so do that for brevity.

diff --git a/include/capab.h b/include/capab.h
index ee253206..972fd4cd 100644
--- a/include/capab.h
+++ b/include/capab.h
@@ -44,18 +44,24 @@
        _CAP(EXTJOIN, FEAT_CAP_EXTJOIN, 0, "extended-join"), \
        _CAP(INVITENOTIFY, FEAT_CAP_INVITENOTIFY, 0, "invite-notify")
 
-/** Client capabilities */
+/** Client capabilities, counting by index. */
 enum Capab {
-#define _CAP(cap, config, flags, name) CAP_ ## cap
+#define _CAP(cap, config, flags, name) E_CAP_ ## cap
   CAPLIST,
 #undef _CAP
-  _CAP_LAST_CAP
+  _E_CAP_LAST_CAP
 };
 
-DECLARE_FLAGSET(CapSet, _CAP_LAST_CAP);
+/** Client capabilities, bit mask version. */
+enum CapabBits {
+#define _CAP(cap, config, flags, name) CAP_ ## cap = 1u << E_CAP_ ## cap
+  CAPLIST,
+#undef _CAP
+  _CAP_LAST_CAP = 1u << _E_CAP_LAST_CAP
+};
 
-#define CapHas(cs, cap)        FlagHas(cs, cap)
-#define CapSet(cs, cap)        FlagSet(cs, cap)
-#define CapClr(cs, cap)        FlagClr(cs, cap)
+#define CapHas(cs, cap)        (cs & cap)
+#define CapSet(cs, cap)        (cs |= cap)
+#define CapClr(cs, cap)        (cs &= ~cap)
 
 #endif /* INCLUDED_capab_h */
diff --git a/include/client.h b/include/client.h
index 4f07cb17..92e4816c 100644
--- a/include/client.h
+++ b/include/client.h
@@ -65,6 +65,9 @@ struct AuthRequest;
  * source file, or in the source file itself (when only used in that file).
  */
 
+/** Value to hold a set of capability bits (from capab.h). */
+typedef unsigned short capset_t;
+
 /** Single element in a flag bitset array. */
 typedef unsigned long flagpage_t;
 
@@ -229,8 +232,8 @@ struct Connection
   struct Timer        con_proc;      /**< process latent messages from
                                       client */
   struct Privs        con_privs;     /**< Oper privileges */
-  struct CapSet       con_capab;     /**< Client capabilities (from us) */
-  struct CapSet       con_active;    /**< Active capabilities (to us) */
+  capset_t            con_capab;     /**< Client capabilities (from us) */
+  capset_t            con_active;    /**< Active capabilities (to us) */
   struct AuthRequest* con_auth;      /**< Auth request for client */
   const struct wline* con_wline;     /**< WebIRC authorization for client */
 };
@@ -460,9 +463,9 @@ struct Client {
 /** Get the oper privilege set for the connection. */
 #define con_privs(con)          (&(con)->con_privs)
 /** Get the peer's capabilities for the connection. */
-#define con_capab(con)          (&(con)->con_capab)
+#define con_capab(con)          ((con)->con_capab)
 /** Get the active capabilities for the connection. */
-#define con_active(con)         (&(con)->con_active)
+#define con_active(con)         ((con)->con_active)
 /** Get the auth request for the connection. */
 #define con_auth(con)          ((con)->con_auth)
 /** Get the WebIRC block (if any) used by the connection. */
diff --git a/ircd/channel.c b/ircd/channel.c
index 93e98c04..2befe56f 100644
--- a/ircd/channel.c
+++ b/ircd/channel.c
@@ -3557,14 +3557,14 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel 
*chan, unsigned int flags)
     if (!((chan->mode.mode & MODE_DELJOINS) && !(flags & 
CHFL_VOICED_OR_OPPED))) {
       /* Send the notification to the channel */
       sendcmdto_capflag_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, 
chan, NULL, 0,
-        _CAP_LAST_CAP, CAP_EXTJOIN, "%H", chan);
+        0, CAP_EXTJOIN, "%H", chan);
       sendcmdto_capflag_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, 
chan, NULL, 0,
-        CAP_EXTJOIN, _CAP_LAST_CAP, "%H %s :%s", chan,
+        CAP_EXTJOIN, 0, "%H %s :%s", chan,
         IsAccount(jbuf->jb_source) ? cli_account(jbuf->jb_source) : "*",
         cli_info(jbuf->jb_source));
       if (cli_user(jbuf->jb_source)->away)
         sendcmdto_capflag_common_channels_butone(jbuf->jb_source, CMD_AWAY, 
jbuf->jb_connect,
-          CAP_AWAYNOTIFY, _CAP_LAST_CAP, ":%s", 
cli_user(jbuf->jb_source)->away);
+          CAP_AWAYNOTIFY, 0, ":%s", cli_user(jbuf->jb_source)->away);
 
       /* send an op, too, if needed */
       if (flags & CHFL_CHANOP && (oplevel < MAXOPLEVEL || 
!MyUser(jbuf->jb_source)))
@@ -3657,9 +3657,9 @@ void RevealDelayedJoin(struct Membership *member)
 {
   ClearDelayedJoin(member);
   sendcmdto_capflag_channel_butserv_butone(member->user, CMD_JOIN, 
member->channel, NULL, 0,
-        _CAP_LAST_CAP, CAP_EXTJOIN, "%H", member->channel);
+        0, CAP_EXTJOIN, "%H", member->channel);
   sendcmdto_capflag_channel_butserv_butone(member->user, CMD_JOIN, 
member->channel, NULL, 0,
-        CAP_EXTJOIN, _CAP_LAST_CAP, "%H %s :%s", member->channel,
+        CAP_EXTJOIN, 0, "%H %s :%s", member->channel,
         IsAccount(member->user) ? cli_account(member->user) : "*",
         cli_info(member->user));
 
diff --git a/ircd/m_account.c b/ircd/m_account.c
index 0e972112..05ddf8d9 100644
--- a/ircd/m_account.c
+++ b/ircd/m_account.c
@@ -156,7 +156,7 @@ int ms_account(struct Client* cptr, struct Client* sptr, 
int parc,
     hide_hostmask(acptr, FLAG_ACCOUNT);
 
     sendcmdto_capflag_common_channels_butone(acptr, CMD_ACCOUNT, NULL, 
CAP_ACCOUNTNOTIFY,
-                          _CAP_LAST_CAP, "%s", cli_user(acptr)->account);
+                          0, "%s", cli_user(acptr)->account);
   }
 
   if (parc > 4) {
diff --git a/ircd/m_away.c b/ircd/m_away.c
index e713d17f..a4a78650 100644
--- a/ircd/m_away.c
+++ b/ircd/m_away.c
@@ -164,14 +164,14 @@ int m_away(struct Client* cptr, struct Client* sptr, int 
parc, char* parv[])
     if (!was_away)
     {
       sendcmdto_serv_butone(sptr, CMD_AWAY, cptr, ":%s", away_message);
-      sendcmdto_capflag_common_channels_butone(sptr, CMD_AWAY, cptr, 
CAP_AWAYNOTIFY, _CAP_LAST_CAP, ":%s", away_message);
+      sendcmdto_capflag_common_channels_butone(sptr, CMD_AWAY, cptr, 
CAP_AWAYNOTIFY, 0, ":%s", away_message);
     }
 
     send_reply(sptr, RPL_NOWAWAY);
   }
   else {
     sendcmdto_serv_butone(sptr, CMD_AWAY, cptr, "");
-    sendcmdto_capflag_common_channels_butone(sptr, CMD_AWAY, cptr, 
CAP_AWAYNOTIFY, _CAP_LAST_CAP, "");
+    sendcmdto_capflag_common_channels_butone(sptr, CMD_AWAY, cptr, 
CAP_AWAYNOTIFY, 0, "");
     send_reply(sptr, RPL_UNAWAY);
   }
   return 0;
diff --git a/ircd/m_cap.c b/ircd/m_cap.c
index a9323673..2cc0159f 100644
--- a/ircd/m_cap.c
+++ b/ircd/m_cap.c
@@ -53,7 +53,7 @@ static struct capabilities {
   int namelen;
 } capab_list[] = {
 #define _CAP(cap, config, flags, name)      \
-       { CAP_ ## cap, #cap, (config), (flags), (name), sizeof(name) - 1 }
+       { E_CAP_ ## cap, #cap, (config), (flags), (name), sizeof(name) - 1 }
   CAPLIST
 #undef _CAP
 };
@@ -138,8 +138,8 @@ find_cap(const char **caplist_p, int *neg_p)
  * @param[in] subcmd Name of capability subcommand.
  */
 static int
-send_caplist(struct Client *sptr, const struct CapSet *set,
-             const struct CapSet *rem, const char *subcmd)
+send_caplist(struct Client *sptr, capset_t set,
+             capset_t rem, const char *subcmd)
 {
   char capbuf[BUFSIZE] = "", pfx[16];
   struct MsgBuf *mb;
@@ -209,9 +209,9 @@ cap_req(struct Client *sptr, const char *caplist)
 {
   const char *cl = caplist;
   struct capabilities *cap;
-  struct CapSet set, rem;
-  struct CapSet cs = *cli_capab(sptr); /* capability set */
-  struct CapSet as = *cli_active(sptr); /* active set */
+  capset_t set = 0, rem = 0;
+  capset_t cs = cli_capab(sptr); /* capability set */
+  capset_t as = cli_active(sptr); /* active set */
   int neg;
 
   if (IsUserPort(sptr)) /* registration hasn't completed; suspend it... */
@@ -229,24 +229,24 @@ cap_req(struct Client *sptr, const char *caplist)
     }
 
     if (neg) { /* set or clear the capability... */
-      CapSet(&rem, cap->cap);
-      CapClr(&set, cap->cap);
-      CapClr(&cs, cap->cap);
+      CapSet(rem, cap->cap);
+      CapClr(set, cap->cap);
+      CapClr(cs, cap->cap);
       if (!(cap->flags & CAPFL_PROTO))
-       CapClr(&as, cap->cap);
+       CapClr(as, cap->cap);
     } else {
-      CapClr(&rem, cap->cap);
-      CapSet(&set, cap->cap);
-      CapSet(&cs, cap->cap);
+      CapClr(rem, cap->cap);
+      CapSet(set, cap->cap);
+      CapSet(cs, cap->cap);
       if (!(cap->flags & CAPFL_PROTO))
-       CapSet(&as, cap->cap);
+       CapSet(as, cap->cap);
     }
   }
 
   /* Notify client of accepted changes and copy over results. */
-  send_caplist(sptr, &set, &rem, "ACK");
-  *cli_capab(sptr) = cs;
-  *cli_active(sptr) = as;
+  send_caplist(sptr, set, rem, "ACK");
+  cli_capab(sptr) = cs;
+  cli_active(sptr) = as;
 
   return 0;
 }
@@ -284,24 +284,23 @@ cap_ack(struct Client *sptr, const char *caplist)
 static int
 cap_clear(struct Client *sptr, const char *caplist)
 {
-  struct CapSet cleared;
+  capset_t cleared = 0;
   struct capabilities *cap;
   unsigned int ii;
 
   /* XXX: If we ever add a capab list sorted by capab value, it would
    * be good cache-wise to use it here. */
-  memset(&cleared, 0, sizeof(cleared));
   for (ii = 0; ii < CAPAB_LIST_LEN; ++ii) {
     cap = &capab_list[ii];
     /* Only clear active non-sticky capabilities. */
     if (!HasCap(sptr, cap->cap) || (cap->flags & CAPFL_STICKY))
       continue;
-    CapSet(&cleared, cap->cap);
+    CapSet(cleared, cap->cap);
     CapClr(cli_capab(sptr), cap->cap);
     if (!(cap->flags & CAPFL_PROTO))
       CapClr(cli_active(sptr), cap->cap);
   }
-  send_caplist(sptr, 0, &cleared, "ACK");
+  send_caplist(sptr, 0, cleared, "ACK");
 
   return 0;
 }
diff --git a/ircd/m_invite.c b/ircd/m_invite.c
index 33d4d691..48c29670 100644
--- a/ircd/m_invite.c
+++ b/ircd/m_invite.c
@@ -189,14 +189,14 @@ int m_invite(struct Client* cptr, struct Client* sptr, 
int parc, char* parv[])
      */
     sendcmdto_capflag_channel_butserv_butone(sptr, CMD_INVITE,
                                              chptr, sptr, SKIP_NONOPS,
-                                             CAP_INVITENOTIFY, _CAP_LAST_CAP,
+                                             CAP_INVITENOTIFY, 0,
                                              "%C %H", acptr, chptr);
 
     if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
       /* Announce to channel operators without CAP_INVITENOTIFY enabled. */
       sendcmdto_capflag_channel_butserv_butone(&his, 
get_error_numeric(RPL_ISSUEDINVITE)->str,
                                                NULL, chptr, sptr, SKIP_NONOPS,
-                                               _CAP_LAST_CAP, CAP_INVITENOTIFY,
+                                               0, CAP_INVITENOTIFY,
                                                "%H %C %C :%C has been invited 
by %C",
                                                chptr, acptr, sptr, acptr, 
sptr);
       /* Announce to servers with channel operators. */
@@ -300,14 +300,14 @@ int ms_invite(struct Client* cptr, struct Client* sptr, 
int parc, char* parv[])
   /* Announce to channel operators with CAP_NOTIFY enabled. */
   sendcmdto_capflag_channel_butserv_butone(sptr, CMD_INVITE,
                                            chptr, sptr, SKIP_NONOPS,
-                                           CAP_INVITENOTIFY, _CAP_LAST_CAP,
+                                           CAP_INVITENOTIFY, 0,
                                            "%C %H", acptr, chptr);
 
   if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
     /* Announce to channel operators without CAP_NOTIFY enabled. */
     sendcmdto_capflag_channel_butserv_butone(&his, 
get_error_numeric(RPL_ISSUEDINVITE)->str,
                                              NULL, chptr, sptr, SKIP_NONOPS,
-                                             _CAP_LAST_CAP, CAP_INVITENOTIFY,
+                                             0, CAP_INVITENOTIFY,
                                              "%H %C %C :%C has been invited by 
%C",
                                              chptr, acptr, sptr, acptr, sptr);
     /* Announce to servers with channel operators. */
diff --git a/ircd/s_user.c b/ircd/s_user.c
index b4f2d783..33296dba 100644
--- a/ircd/s_user.c
+++ b/ircd/s_user.c
@@ -903,8 +903,8 @@ hide_hostmask(struct Client *cptr, unsigned int flag)
   if (!HasFlag(cptr, FLAG_HIDDENHOST) || !HasFlag(cptr, FLAG_ACCOUNT))
     return 0;
 
-  sendcmdto_capflag_common_channels_butone(cptr, CMD_QUIT, cptr, 
_CAP_LAST_CAP, CAP_CHGHOST, ":Registered");
-  sendcmdto_capflag_common_channels_butone(cptr, CMD_CHGHOST, NULL, 
CAP_CHGHOST, _CAP_LAST_CAP, "%s %s.%s",
+  sendcmdto_capflag_common_channels_butone(cptr, CMD_QUIT, cptr, 0, 
CAP_CHGHOST, ":Registered");
+  sendcmdto_capflag_common_channels_butone(cptr, CMD_CHGHOST, NULL, 
CAP_CHGHOST, 0, "%s %s.%s",
     cli_user(cptr)->username, cli_user(cptr)->account, 
feature_str(FEAT_HIDDEN_HOST));
   ircd_snprintf(0, cli_user(cptr)->host, HOSTLEN, "%s.%s",
                 cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST));
@@ -924,14 +924,14 @@ hide_hostmask(struct Client *cptr, unsigned int flag)
     /* Send a JOIN unless the user's join has been delayed. */
     if (!IsDelayedJoin(chan))
       sendcmdto_capflag_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, 
cptr, 0,
-                                         _CAP_LAST_CAP, CAP_CHGHOST, "%H", 
chan->channel);
+                                         0, CAP_CHGHOST, "%H", chan->channel);
     if (IsChanOp(chan) && HasVoice(chan))
       sendcmdto_capflag_channel_butserv_butone(&his, CMD_MODE, chan->channel, 
cptr, 0,
-                                       _CAP_LAST_CAP, CAP_CHGHOST, "%H +ov %C 
%C", chan->channel, cptr,
+                                       0, CAP_CHGHOST, "%H +ov %C %C", 
chan->channel, cptr,
                                        cptr);
     else if (IsChanOp(chan) || HasVoice(chan))
       sendcmdto_capflag_channel_butserv_butone(&his, CMD_MODE, chan->channel, 
cptr, 0,
-        _CAP_LAST_CAP, CAP_CHGHOST, "%H +%c %C", chan->channel, IsChanOp(chan) 
? 'o' : 'v', cptr);
+        0, CAP_CHGHOST, "%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 
'v', cptr);
   }
   return 0;
 }
diff --git a/ircd/send.c b/ircd/send.c
index ca00f016..a739cc4a 100644
--- a/ircd/send.c
+++ b/ircd/send.c
@@ -559,8 +559,8 @@ void sendcmdto_capflag_common_channels_butone(struct Client 
*from, const char *c
           && -1 < cli_fd(cli_from(member->user))
           && member->user != one
           && cli_sentalong(member->user) != sentalong_marker
-          && (require == _CAP_LAST_CAP || CapHas(cli_active(member->user), 
require))
-          && (forbid == _CAP_LAST_CAP || !CapHas(cli_active(member->user), 
forbid)))
+          && CapHas(cli_active(member->user), require)
+          && !CapHas(cli_active(member->user), forbid))
       {
           cli_sentalong(member->user) = sentalong_marker;
           send_buffer(member->user, mb, 0);
@@ -612,8 +612,8 @@ void sendcmdto_capflag_channel_butserv_butone(struct Client 
*from, const char *c
         || (skip & SKIP_DEAF && IsDeaf(member->user))
         || (skip & SKIP_NONOPS && !IsChanOp(member))
         || (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member))
-        || (require < _CAP_LAST_CAP && !CapHas(cli_active(member->user), 
require))
-        || (forbid < _CAP_LAST_CAP && CapHas(cli_active(member->user), 
forbid)))
+        || !CapHas(cli_active(member->user), require)
+        || CapHas(cli_active(member->user), forbid))
         continue;
 
     send_buffer(member->user, mb, 0);
commit 2e93875f800a6a24e894e9ce7d457fff5609516b
Author: Erik Tørrissen <[email protected]>
Date:   Tue Feb 4 19:40:38 2025 +0100

    Minor fix to CAP handler for unregistered connections.

diff --git a/ircd/m_cap.c b/ircd/m_cap.c
index e37ba96a..a9323673 100644
--- a/ircd/m_cap.c
+++ b/ircd/m_cap.c
@@ -199,7 +199,7 @@ send_caplist(struct Client *sptr, const struct CapSet *set,
 static int
 cap_ls(struct Client *sptr, const char *caplist)
 {
-  if (IsUnknown(sptr)) /* registration hasn't completed; suspend it... */
+  if (IsUserPort(sptr)) /* registration hasn't completed; suspend it... */
     auth_cap_start(cli_auth(sptr));
   return send_caplist(sptr, 0, 0, "LS"); /* send list of capabilities */
 }
@@ -214,7 +214,7 @@ cap_req(struct Client *sptr, const char *caplist)
   struct CapSet as = *cli_active(sptr); /* active set */
   int neg;
 
-  if (IsUnknown(sptr)) /* registration hasn't completed; suspend it... */
+  if (IsUserPort(sptr)) /* registration hasn't completed; suspend it... */
     auth_cap_start(cli_auth(sptr));
 
   memset(&set, 0, sizeof(set));
@@ -309,7 +309,7 @@ cap_clear(struct Client *sptr, const char *caplist)
 static int
 cap_end(struct Client *sptr, const char *caplist)
 {
-  if (!IsUnknown(sptr)) /* registration has completed... */
+  if (!IsUserPort(sptr)) /* registration has completed... */
     return 0; /* so just ignore the message... */
 
   return auth_cap_done(cli_auth(sptr));
-----------------------------------------------------------------------

Summary of changes:
 include/capab.h   | 20 +++++++++++++-------
 include/client.h  | 11 +++++++----
 include/send.h    | 23 ++++++++++++++++++++---
 ircd/channel.c    | 22 +++++++---------------
 ircd/m_account.c  |  5 ++---
 ircd/m_away.c     |  4 ++--
 ircd/m_burst.c    |  8 ++++++--
 ircd/m_cap.c      | 53 +++++++++++++++++++++++++++--------------------------
 ircd/m_destruct.c |  9 +--------
 ircd/m_invite.c   |  8 ++++----
 ircd/m_kick.c     |  4 ++--
 ircd/s_user.c     | 16 ++++++++++------
 ircd/send.c       | 51 +++++++++++++++++++++++++++++++++++++++++++--------
 13 files changed, 144 insertions(+), 90 deletions(-)


hooks/post-receive
-- 
Undernet IRC Server Source Code.

To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].

Reply via email to