X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/7a7f86d3445f86a6bb2fb399c95485ed5e0c7f21..d855e13e01c7f9f616610746dea9bdc55ac4ba2a:/modules/m_cap.c diff --git a/modules/m_cap.c b/modules/m_cap.c index aa2693a8..2472d4cb 100644 --- a/modules/m_cap.c +++ b/modules/m_cap.c @@ -1,5 +1,5 @@ /* modules/m_cap.c - * + * * Copyright (C) 2005 Lee Hardy * Copyright (C) 2005 ircd-ratbox development team * @@ -41,6 +41,9 @@ #include "modules.h" #include "s_serv.h" #include "s_user.h" +#include "send.h" +#include "s_conf.h" +#include "hash.h" typedef int (*bqcmp)(const void *, const void *); @@ -55,8 +58,8 @@ struct Message cap_msgtab = { mapi_clist_av1 cap_clist[] = { &cap_msgtab, NULL }; DECLARE_MODULE_AV1(cap, modinit, NULL, cap_clist, NULL, NULL, "$Revision: 676 $"); -#define _CLICAP(name, capserv, capclient, flags) \ - { (name), (capserv), (capclient), (flags), sizeof(name) - 1 } +#define _CLICAP(name, capserv, capclient, caprequired, flags) \ + { (name), (capserv), (capclient), (caprequired), (flags), sizeof(name) - 1 } #define CLICAP_FLAGS_STICKY 0x001 @@ -65,12 +68,19 @@ static struct clicap const char *name; int cap_serv; /* for altering s->c */ int cap_cli; /* for altering c->s */ + int cap_required_serv; /* required dependency cap */ int flags; int namelen; } clicap_list[] = { - _CLICAP("multi-prefix", CLICAP_MULTI_PREFIX, 0, 0), - _CLICAP("sasl", CLICAP_SASL, 0, 0), - _CLICAP("account-notify", CLICAP_ACCOUNT_NOTIFY, 0, 0) + _CLICAP("multi-prefix", CLICAP_MULTI_PREFIX, 0, 0, 0), + _CLICAP("sasl", CLICAP_SASL, 0, 0, CLICAP_FLAGS_STICKY), + _CLICAP("account-notify", CLICAP_ACCOUNT_NOTIFY, 0, 0, 0), + _CLICAP("extended-join", CLICAP_EXTENDED_JOIN, 0, 0, 0), + _CLICAP("away-notify", CLICAP_AWAY_NOTIFY, 0, 0, 0), + _CLICAP("tls", CLICAP_TLS, 0, 0, 0), + _CLICAP("userhost-in-names", CLICAP_USERHOST_IN_NAMES, 0, 0, 0), + _CLICAP("cap-notify", CLICAP_CAP_NOTIFY, 0, 0, 0), + _CLICAP("chghost", CLICAP_CHGHOST, 0, 0, 0), }; #define CLICAP_LIST_LEN (sizeof(clicap_list) / sizeof(struct clicap)) @@ -147,7 +157,7 @@ clicap_find(const char *data, int *negate, int *finished) if((s = strchr(p, ' '))) *s++ = '\0'; - if((cap = bsearch(p, clicap_list, CLICAP_LIST_LEN, + if((cap = bsearch(p, clicap_list, CLICAP_LIST_LEN, sizeof(struct clicap), (bqcmp) clicap_compare))) { if(s) @@ -178,8 +188,8 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea size_t i; mlen = rb_sprintf(buf, ":%s CAP %s %s", - me.name, - EmptyString(source_p->name) ? "*" : source_p->name, + me.name, + EmptyString(source_p->name) ? "*" : source_p->name, subcmd); p = capbuf; @@ -203,6 +213,18 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea continue; } + if (clicap_list[i].cap_serv == CLICAP_SASL) + { + struct Client *agent_p = NULL; + + if (!ConfigFileEntry.sasl_service) + continue; + + agent_p = find_named_client(ConfigFileEntry.sasl_service); + if (agent_p == NULL || !IsService(agent_p)) + continue; + } + /* \r\n\0, possible "-~=", space, " *" */ if(buflen + clicap_list[i].namelen >= BUFSIZE - 10) { @@ -223,32 +245,6 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea { *p++ = '-'; buflen++; - - /* needs a client ack */ - if(clicap_list[i].cap_cli && - IsCapable(source_p, clicap_list[i].cap_cli)) - { - *p++ = '~'; - buflen++; - } - } - else - { - if(clicap_list[i].flags & CLICAP_FLAGS_STICKY) - { - *p++ = '='; - buflen++; - } - - /* if we're doing an LS, then we only send this if - * they havent ack'd - */ - if(clicap_list[i].cap_cli && - (!flags || !IsCapable(source_p, clicap_list[i].cap_cli))) - { - *p++ = '~'; - buflen++; - } } curlen = rb_sprintf(p, "%s ", clicap_list[i].name); @@ -301,7 +297,7 @@ cap_ack(struct Client *source_p, const char *arg) static void cap_clear(struct Client *source_p, const char *arg) { - clicap_generate(source_p, "ACK", + clicap_generate(source_p, "ACK", source_p->localClient->caps ? source_p->localClient->caps : -1, 1); /* XXX - sticky capabs */ @@ -322,9 +318,7 @@ cap_end(struct Client *source_p, const char *arg) if(source_p->name[0] && source_p->flags & FLAGS_SENTUSER) { - char buf[USERLEN+1]; - rb_strlcpy(buf, source_p->username, sizeof(buf)); - register_local_user(source_p, source_p, buf); + register_local_user(source_p, source_p); } } @@ -398,10 +392,28 @@ cap_req(struct Client *source_p, const char *arg) } else { - if(cap->flags & CLICAP_FLAGS_STICKY) + if(cap->cap_required_serv && !((capadd & cap->cap_required_serv) == cap->cap_required_serv || IsCapable(source_p, cap->cap_required_serv))) { - strcat(pbuf[i], "="); - plen++; + finished = 0; + break; + } + + if (cap->cap_serv == CLICAP_SASL) + { + struct Client *agent_p = NULL; + + if (!ConfigFileEntry.sasl_service) + { + finished = 0; + break; + } + + agent_p = find_named_client(ConfigFileEntry.sasl_service); + if (agent_p == NULL || !IsService(agent_p)) + { + finished = 0; + break; + } } capadd |= cap->cap_serv; @@ -414,8 +426,10 @@ cap_req(struct Client *source_p, const char *arg) } strcat(pbuf[i], cap->name); - strcat(pbuf[i], " "); - plen += (cap->namelen + 1); + if (!finished) { + strcat(pbuf[i], " "); + plen += (cap->namelen + 1); + } } if(!finished)