diff --git a/include/s_serv.h b/include/s_serv.h index e3893dcb..1c15b014 100644 --- a/include/s_serv.h +++ b/include/s_serv.h @@ -51,6 +51,7 @@ extern struct CapabilityIndex *cli_capindex; /* register client capabilities with this structure for 3.2 enhanced capability negotiation */ #define CLICAP_FLAGS_STICKY 0x001 +#define CLICAP_FLAGS_PRIORITY 0x002 struct ClientCapability { bool (*visible)(struct Client *); /* whether or not to display the capability. set to NULL or true return value = displayed */ diff --git a/ircd/s_serv.c b/ircd/s_serv.c index f4003260..7eabf27c 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -103,6 +103,7 @@ unsigned int CLICAP_ECHO_MESSAGE; void init_builtin_capabs(void) { + static struct ClientCapability high_priority = {.flags = CLICAP_FLAGS_PRIORITY}; serv_capindex = capability_index_create("server capabilities"); /* These two are not set via CAPAB/GCAP keywords. */ @@ -135,13 +136,13 @@ init_builtin_capabs(void) cli_capindex = capability_index_create("client capabilities"); - CLICAP_MULTI_PREFIX = capability_put(cli_capindex, "multi-prefix", NULL); - CLICAP_ACCOUNT_NOTIFY = capability_put(cli_capindex, "account-notify", NULL); - CLICAP_EXTENDED_JOIN = capability_put(cli_capindex, "extended-join", NULL); - CLICAP_AWAY_NOTIFY = capability_put(cli_capindex, "away-notify", NULL); - CLICAP_USERHOST_IN_NAMES = capability_put(cli_capindex, "userhost-in-names", NULL); + CLICAP_MULTI_PREFIX = capability_put(cli_capindex, "multi-prefix", &high_priority); + CLICAP_ACCOUNT_NOTIFY = capability_put(cli_capindex, "account-notify", &high_priority); + CLICAP_EXTENDED_JOIN = capability_put(cli_capindex, "extended-join", &high_priority); + CLICAP_AWAY_NOTIFY = capability_put(cli_capindex, "away-notify", &high_priority); + CLICAP_USERHOST_IN_NAMES = capability_put(cli_capindex, "userhost-in-names", &high_priority); CLICAP_CAP_NOTIFY = capability_put(cli_capindex, "cap-notify", NULL); - CLICAP_CHGHOST = capability_put(cli_capindex, "chghost", NULL); + CLICAP_CHGHOST = capability_put(cli_capindex, "chghost", &high_priority); CLICAP_ECHO_MESSAGE = capability_put(cli_capindex, "echo-message", NULL); } diff --git a/modules/m_cap.c b/modules/m_cap.c index 26215028..9572b30c 100644 --- a/modules/m_cap.c +++ b/modules/m_cap.c @@ -177,10 +177,16 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags) buf_list[0] = '\0'; max_list = sizeof(buf_prefix) - len_prefix - strlen(str_cont); + for (int pass = 0; pass < 2; pass++) RB_DICTIONARY_FOREACH(entry, &iter, cli_capindex->cap_dict) { struct ClientCapability *clicap = entry->ownerdata; const char *data = NULL; + if (pass == 0 && !HasCapabilityFlag(entry, CLICAP_FLAGS_PRIORITY)) + continue; + else if (pass == 1 && HasCapabilityFlag(entry, CLICAP_FLAGS_PRIORITY)) + continue; + if (flags && !IsCapableEntry(source_p, entry)) continue; diff --git a/modules/m_sasl.c b/modules/m_sasl.c index e8217aa6..3ac5a139 100644 --- a/modules/m_sasl.c +++ b/modules/m_sasl.c @@ -106,7 +106,7 @@ sasl_data(struct Client *client_p) static struct ClientCapability capdata_sasl = { .visible = sasl_visible, .data = sasl_data, - .flags = CLICAP_FLAGS_STICKY, + .flags = CLICAP_FLAGS_STICKY | CLICAP_FLAGS_PRIORITY, }; mapi_cap_list_av2 sasl_cap_list[] = { diff --git a/modules/m_starttls.c b/modules/m_starttls.c index c5b98a07..a51f652f 100644 --- a/modules/m_starttls.c +++ b/modules/m_starttls.c @@ -45,8 +45,12 @@ mapi_clist_av1 starttls_clist[] = { &starttls_msgtab, NULL }; unsigned int CLICAP_TLS = 0; +static struct ClientCapability capdata_tls = { + .flags = CLICAP_FLAGS_PRIORITY, +}; + mapi_cap_list_av2 starttls_cap_list[] = { - { MAPI_CAP_CLIENT, "tls", NULL, &CLICAP_TLS }, + { MAPI_CAP_CLIENT, "tls", &capdata_tls, &CLICAP_TLS }, { 0, NULL, NULL, NULL } };