mirror of
https://github.com/matrix-construct/construct
synced 2024-11-16 06:51:08 +01:00
cap: substantial rewrite leveraging the ircd capabilities framework for client caps
This commit is contained in:
parent
ba83226733
commit
32df5e96a6
7 changed files with 101 additions and 102 deletions
|
@ -38,6 +38,7 @@ struct CapabilityEntry {
|
||||||
void *ownerdata;
|
void *ownerdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct CapabilityEntry *capability_find(struct CapabilityIndex *idx, const char *cap);
|
||||||
extern unsigned int capability_get(struct CapabilityIndex *idx, const char *cap, void **ownerdata);
|
extern unsigned int capability_get(struct CapabilityIndex *idx, const char *cap, void **ownerdata);
|
||||||
extern unsigned int capability_put(struct CapabilityIndex *idx, const char *cap, void *ownerdata);
|
extern unsigned int capability_put(struct CapabilityIndex *idx, const char *cap, void *ownerdata);
|
||||||
extern unsigned int capability_put_anonymous(struct CapabilityIndex *idx);
|
extern unsigned int capability_put_anonymous(struct CapabilityIndex *idx);
|
||||||
|
|
|
@ -445,18 +445,6 @@ struct ListClient
|
||||||
UMODE_WALLOP | UMODE_LOCOPS)
|
UMODE_WALLOP | UMODE_LOCOPS)
|
||||||
#define DEFAULT_OPER_SNOMASK SNO_GENERAL
|
#define DEFAULT_OPER_SNOMASK SNO_GENERAL
|
||||||
|
|
||||||
/* XXX make clicap a registry */
|
|
||||||
#define CLICAP_MULTI_PREFIX 0x0001
|
|
||||||
#define CLICAP_SASL 0x0002
|
|
||||||
#define CLICAP_ACCOUNT_NOTIFY 0x0004
|
|
||||||
#define CLICAP_EXTENDED_JOIN 0x0008
|
|
||||||
#define CLICAP_AWAY_NOTIFY 0x0010
|
|
||||||
#define CLICAP_TLS 0x0020
|
|
||||||
#define CLICAP_USERHOST_IN_NAMES 0x0040
|
|
||||||
#define CLICAP_CAP_NOTIFY 0x0080
|
|
||||||
#define CLICAP_CHGHOST 0x0100
|
|
||||||
#define CLICAP_ACCOUNT_TAG 0x0200
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* flags macros.
|
* flags macros.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -51,6 +51,28 @@ struct Channel;
|
||||||
extern struct CapabilityIndex *serv_capindex;
|
extern struct CapabilityIndex *serv_capindex;
|
||||||
extern struct CapabilityIndex *cli_capindex;
|
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_REQACK 0x002
|
||||||
|
|
||||||
|
struct ClientCapability {
|
||||||
|
int (*visible)(void); /* whether or not to display the capability. set to NULL or true return value = displayed */
|
||||||
|
const char *(*data)(void); /* any custom data for the capability. set to NULL or return NULL = no data */
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* builtin client capabilities */
|
||||||
|
extern unsigned int CLICAP_MULTI_PREFIX;
|
||||||
|
extern unsigned int CLICAP_SASL;
|
||||||
|
extern unsigned int CLICAP_ACCOUNT_NOTIFY;
|
||||||
|
extern unsigned int CLICAP_EXTENDED_JOIN;
|
||||||
|
extern unsigned int CLICAP_AWAY_NOTIFY;
|
||||||
|
extern unsigned int CLICAP_TLS;
|
||||||
|
extern unsigned int CLICAP_USERHOST_IN_NAMES;
|
||||||
|
extern unsigned int CLICAP_CAP_NOTIFY;
|
||||||
|
extern unsigned int CLICAP_CHGHOST;
|
||||||
|
extern unsigned int CLICAP_ACCOUNT_TAG;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: this is kind of ugly, but this allows us to have backwards
|
* XXX: this is kind of ugly, but this allows us to have backwards
|
||||||
* API-compatibility.
|
* API-compatibility.
|
||||||
|
|
|
@ -25,6 +25,16 @@
|
||||||
|
|
||||||
static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
|
static rb_dlink_list capability_indexes = { NULL, NULL, 0 };
|
||||||
|
|
||||||
|
struct CapabilityEntry *
|
||||||
|
capability_find(struct CapabilityIndex *idx, const char *cap)
|
||||||
|
{
|
||||||
|
s_assert(idx != NULL);
|
||||||
|
if (cap == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return irc_dictionary_retrieve(idx->cap_dict, cap);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
capability_get(struct CapabilityIndex *idx, const char *cap, void **ownerdata)
|
capability_get(struct CapabilityIndex *idx, const char *cap, void **ownerdata)
|
||||||
{
|
{
|
||||||
|
|
|
@ -95,6 +95,16 @@ unsigned int CAP_EOPMOD;
|
||||||
unsigned int CAP_BAN;
|
unsigned int CAP_BAN;
|
||||||
unsigned int CAP_MLOCK;
|
unsigned int CAP_MLOCK;
|
||||||
|
|
||||||
|
unsigned int CLICAP_MULTI_PREFIX;
|
||||||
|
unsigned int CLICAP_SASL;
|
||||||
|
unsigned int CLICAP_ACCOUNT_NOTIFY;
|
||||||
|
unsigned int CLICAP_EXTENDED_JOIN;
|
||||||
|
unsigned int CLICAP_AWAY_NOTIFY;
|
||||||
|
unsigned int CLICAP_TLS;
|
||||||
|
unsigned int CLICAP_USERHOST_IN_NAMES;
|
||||||
|
unsigned int CLICAP_CAP_NOTIFY;
|
||||||
|
unsigned int CLICAP_CHGHOST;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize our builtin capability table. --nenolod
|
* initialize our builtin capability table. --nenolod
|
||||||
*/
|
*/
|
||||||
|
@ -132,6 +142,16 @@ init_builtin_capabs(void)
|
||||||
capability_require(serv_capindex, "ENCAP");
|
capability_require(serv_capindex, "ENCAP");
|
||||||
|
|
||||||
cli_capindex = capability_index_create("client capabilities");
|
cli_capindex = capability_index_create("client capabilities");
|
||||||
|
|
||||||
|
CLICAP_MULTI_PREFIX = capability_put(cli_capindex, "multi-prefix", NULL);
|
||||||
|
CLICAP_SASL = capability_put(cli_capindex, "sasl", 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_TLS = capability_put(cli_capindex, "tls", NULL);
|
||||||
|
CLICAP_USERHOST_IN_NAMES = capability_put(cli_capindex, "userhost-in-names", NULL);
|
||||||
|
CLICAP_CAP_NOTIFY = capability_put(cli_capindex, "cap-notify", NULL);
|
||||||
|
CLICAP_CHGHOST = capability_put(cli_capindex, "chghost", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static CNCB serv_connect_callback;
|
static CNCB serv_connect_callback;
|
||||||
|
|
|
@ -41,6 +41,8 @@ mapi_hfn_list_av1 cap_account_tag_hfnlist[] = {
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
unsigned int CLICAP_ACCOUNT_TAG = 0;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cap_account_tag_process(hook_data *data)
|
cap_account_tag_process(hook_data *data)
|
||||||
{
|
{
|
||||||
|
@ -50,4 +52,17 @@ cap_account_tag_process(hook_data *data)
|
||||||
msgbuf_append_tag(msgbuf, "account", data->client->user->suser, CLICAP_ACCOUNT_TAG);
|
msgbuf_append_tag(msgbuf, "account", data->client->user->suser, CLICAP_ACCOUNT_TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_MODULE_AV1(cap_account_tag, NULL, NULL, NULL, NULL, cap_account_tag_hfnlist, "$Revision$");
|
static int
|
||||||
|
_modinit(void)
|
||||||
|
{
|
||||||
|
CLICAP_ACCOUNT_TAG = capability_put(cli_capindex, "account-tag", NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_moddeinit(void)
|
||||||
|
{
|
||||||
|
capability_orphan(cli_capindex, "account-tag");
|
||||||
|
}
|
||||||
|
|
||||||
|
DECLARE_MODULE_AV1(cap_account_tag, _modinit, _moddeinit, NULL, NULL, cap_account_tag_hfnlist, "$Revision$");
|
||||||
|
|
121
modules/m_cap.c
121
modules/m_cap.c
|
@ -2,6 +2,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2005 Lee Hardy <lee@leeh.co.uk>
|
* Copyright (C) 2005 Lee Hardy <lee@leeh.co.uk>
|
||||||
* Copyright (C) 2005 ircd-ratbox development team
|
* Copyright (C) 2005 ircd-ratbox development team
|
||||||
|
* Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions are
|
* modification, are permitted provided that the following conditions are
|
||||||
|
@ -26,8 +27,6 @@
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
|
||||||
* $Id: m_cap.c 676 2006-02-03 20:05:09Z gxti $
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "stdinc.h"
|
#include "stdinc.h"
|
||||||
|
@ -48,7 +47,6 @@
|
||||||
typedef int (*bqcmp)(const void *, const void *);
|
typedef int (*bqcmp)(const void *, const void *);
|
||||||
|
|
||||||
static int m_cap(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
static int m_cap(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
|
||||||
static int modinit(void);
|
|
||||||
|
|
||||||
struct Message cap_msgtab = {
|
struct Message cap_msgtab = {
|
||||||
"CAP", 0, 0, 0, 0,
|
"CAP", 0, 0, 0, 0,
|
||||||
|
@ -56,57 +54,10 @@ struct Message cap_msgtab = {
|
||||||
};
|
};
|
||||||
|
|
||||||
mapi_clist_av1 cap_clist[] = { &cap_msgtab, NULL };
|
mapi_clist_av1 cap_clist[] = { &cap_msgtab, NULL };
|
||||||
DECLARE_MODULE_AV1(cap, modinit, NULL, cap_clist, NULL, NULL, "$Revision: 676 $");
|
DECLARE_MODULE_AV1(cap, NULL, NULL, cap_clist, NULL, NULL, "$Revision: 676 $");
|
||||||
|
|
||||||
#define _CLICAP(name, capserv, capclient, caprequired, flags) \
|
#define IsCapableEntry(c, e) IsCapable(c, 1 << (e)->value)
|
||||||
{ (name), (capserv), (capclient), (caprequired), (flags), sizeof(name) - 1 }
|
#define HasCapabilityFlag(c, f) (c->ownerdata != NULL && (((struct ClientCapability *)c->ownerdata)->flags & (f)) == f)
|
||||||
|
|
||||||
#define CLICAP_FLAGS_STICKY 0x001
|
|
||||||
|
|
||||||
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, 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),
|
|
||||||
_CLICAP("account-tag", CLICAP_ACCOUNT_TAG, 0, 0, 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CLICAP_LIST_LEN (sizeof(clicap_list) / sizeof(struct clicap))
|
|
||||||
|
|
||||||
static int clicap_sort(struct clicap *, struct clicap *);
|
|
||||||
|
|
||||||
static int
|
|
||||||
modinit(void)
|
|
||||||
{
|
|
||||||
qsort(clicap_list, CLICAP_LIST_LEN, sizeof(struct clicap),
|
|
||||||
(bqcmp) clicap_sort);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
clicap_sort(struct clicap *one, struct clicap *two)
|
|
||||||
{
|
|
||||||
return irccmp(one->name, two->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
clicap_compare(const char *name, struct clicap *cap)
|
|
||||||
{
|
|
||||||
return irccmp(name, cap->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clicap_find()
|
/* clicap_find()
|
||||||
* Used iteratively over a buffer, extracts individual cap tokens.
|
* Used iteratively over a buffer, extracts individual cap tokens.
|
||||||
|
@ -116,12 +67,12 @@ clicap_compare(const char *name, struct clicap *cap)
|
||||||
* int pointer to whether we finish with success
|
* int pointer to whether we finish with success
|
||||||
* Ouputs: Cap entry if found, NULL otherwise.
|
* Ouputs: Cap entry if found, NULL otherwise.
|
||||||
*/
|
*/
|
||||||
static struct clicap *
|
static struct CapabilityEntry *
|
||||||
clicap_find(const char *data, int *negate, int *finished)
|
clicap_find(const char *data, int *negate, int *finished)
|
||||||
{
|
{
|
||||||
static char buf[BUFSIZE];
|
static char buf[BUFSIZE];
|
||||||
static char *p;
|
static char *p;
|
||||||
struct clicap *cap;
|
struct CapabilityEntry *cap;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
*negate = 0;
|
*negate = 0;
|
||||||
|
@ -158,8 +109,7 @@ clicap_find(const char *data, int *negate, int *finished)
|
||||||
if((s = strchr(p, ' ')))
|
if((s = strchr(p, ' ')))
|
||||||
*s++ = '\0';
|
*s++ = '\0';
|
||||||
|
|
||||||
if((cap = bsearch(p, clicap_list, CLICAP_LIST_LEN,
|
if((cap = capability_find(cli_capindex, p)) != NULL)
|
||||||
sizeof(struct clicap), (bqcmp) clicap_compare)))
|
|
||||||
{
|
{
|
||||||
if(s)
|
if(s)
|
||||||
p = s;
|
p = s;
|
||||||
|
@ -186,7 +136,8 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea
|
||||||
char *p;
|
char *p;
|
||||||
int buflen = 0;
|
int buflen = 0;
|
||||||
int curlen, mlen;
|
int curlen, mlen;
|
||||||
size_t i;
|
struct CapabilityEntry *entry;
|
||||||
|
struct DictionaryIter iter;
|
||||||
|
|
||||||
mlen = sprintf(buf, ":%s CAP %s %s",
|
mlen = sprintf(buf, ":%s CAP %s %s",
|
||||||
me.name,
|
me.name,
|
||||||
|
@ -203,18 +154,18 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < CLICAP_LIST_LEN; i++)
|
DICTIONARY_FOREACH(entry, &iter, cli_capindex->cap_dict)
|
||||||
{
|
{
|
||||||
if(flags)
|
if(flags)
|
||||||
{
|
{
|
||||||
if(!IsCapable(source_p, clicap_list[i].cap_serv))
|
if(!IsCapableEntry(source_p, entry))
|
||||||
continue;
|
continue;
|
||||||
/* they are capable of this, check sticky */
|
/* they are capable of this, check sticky */
|
||||||
else if(clear && clicap_list[i].flags & CLICAP_FLAGS_STICKY)
|
else if(clear && HasCapabilityFlag(entry, CLICAP_FLAGS_STICKY))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clicap_list[i].cap_serv == CLICAP_SASL)
|
if ((1 << entry->value) == CLICAP_SASL)
|
||||||
{
|
{
|
||||||
struct Client *agent_p = NULL;
|
struct Client *agent_p = NULL;
|
||||||
|
|
||||||
|
@ -227,7 +178,7 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \r\n\0, possible "-~=", space, " *" */
|
/* \r\n\0, possible "-~=", space, " *" */
|
||||||
if(buflen + clicap_list[i].namelen >= BUFSIZE - 10)
|
if(buflen + strlen(entry->cap) >= BUFSIZE - 10)
|
||||||
{
|
{
|
||||||
/* remove our trailing space -- if buflen == mlen
|
/* remove our trailing space -- if buflen == mlen
|
||||||
* here, we didnt even succeed in adding one.
|
* here, we didnt even succeed in adding one.
|
||||||
|
@ -248,7 +199,7 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea
|
||||||
buflen++;
|
buflen++;
|
||||||
}
|
}
|
||||||
|
|
||||||
curlen = sprintf(p, "%s ", clicap_list[i].name);
|
curlen = sprintf(p, "%s ", entry->cap);
|
||||||
p += curlen;
|
p += curlen;
|
||||||
buflen += curlen;
|
buflen += curlen;
|
||||||
}
|
}
|
||||||
|
@ -265,7 +216,7 @@ clicap_generate(struct Client *source_p, const char *subcmd, int flags, int clea
|
||||||
static void
|
static void
|
||||||
cap_ack(struct Client *source_p, const char *arg)
|
cap_ack(struct Client *source_p, const char *arg)
|
||||||
{
|
{
|
||||||
struct clicap *cap;
|
struct CapabilityEntry *cap;
|
||||||
int capadd = 0, capdel = 0;
|
int capadd = 0, capdel = 0;
|
||||||
int finished = 0, negate;
|
int finished = 0, negate;
|
||||||
|
|
||||||
|
@ -276,19 +227,19 @@ cap_ack(struct Client *source_p, const char *arg)
|
||||||
cap = clicap_find(NULL, &negate, &finished))
|
cap = clicap_find(NULL, &negate, &finished))
|
||||||
{
|
{
|
||||||
/* sent an ACK for something they havent REQd */
|
/* sent an ACK for something they havent REQd */
|
||||||
if(!IsCapable(source_p, cap->cap_serv))
|
if(!IsCapableEntry(source_p, cap))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(negate)
|
if(negate)
|
||||||
{
|
{
|
||||||
/* dont let them ack something sticky off */
|
/* dont let them ack something sticky off */
|
||||||
if(cap->flags & CLICAP_FLAGS_STICKY)
|
if(HasCapabilityFlag(cap, CLICAP_FLAGS_STICKY))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
capdel |= cap->cap_cli;
|
capdel |= (1 << cap->value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
capadd |= cap->cap_cli;
|
capadd |= (1 << cap->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
source_p->localClient->caps |= capadd;
|
source_p->localClient->caps |= capadd;
|
||||||
|
@ -301,12 +252,7 @@ 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);
|
source_p->localClient->caps ? source_p->localClient->caps : -1, 1);
|
||||||
|
|
||||||
/* XXX - sticky capabs */
|
|
||||||
#ifdef CLICAP_STICKY
|
|
||||||
source_p->localClient->caps = source_p->localClient->caps & CLICAP_STICKY;
|
|
||||||
#else
|
|
||||||
source_p->localClient->caps = 0;
|
source_p->localClient->caps = 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -346,7 +292,7 @@ cap_req(struct Client *source_p, const char *arg)
|
||||||
{
|
{
|
||||||
char buf[BUFSIZE];
|
char buf[BUFSIZE];
|
||||||
char pbuf[2][BUFSIZE];
|
char pbuf[2][BUFSIZE];
|
||||||
struct clicap *cap;
|
struct CapabilityEntry *cap;
|
||||||
int buflen, plen;
|
int buflen, plen;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int capadd = 0, capdel = 0;
|
int capadd = 0, capdel = 0;
|
||||||
|
@ -367,11 +313,13 @@ cap_req(struct Client *source_p, const char *arg)
|
||||||
for(cap = clicap_find(arg, &negate, &finished); cap;
|
for(cap = clicap_find(arg, &negate, &finished); cap;
|
||||||
cap = clicap_find(NULL, &negate, &finished))
|
cap = clicap_find(NULL, &negate, &finished))
|
||||||
{
|
{
|
||||||
|
size_t namelen = strlen(cap->cap);
|
||||||
|
|
||||||
/* filled the first array, but cant send it in case the
|
/* filled the first array, but cant send it in case the
|
||||||
* request fails. one REQ should never fill more than two
|
* request fails. one REQ should never fill more than two
|
||||||
* buffers --fl
|
* buffers --fl
|
||||||
*/
|
*/
|
||||||
if(buflen + plen + cap->namelen + 6 >= BUFSIZE)
|
if(buflen + plen + namelen + 6 >= BUFSIZE)
|
||||||
{
|
{
|
||||||
pbuf[1][0] = '\0';
|
pbuf[1][0] = '\0';
|
||||||
plen = 0;
|
plen = 0;
|
||||||
|
@ -380,7 +328,7 @@ cap_req(struct Client *source_p, const char *arg)
|
||||||
|
|
||||||
if(negate)
|
if(negate)
|
||||||
{
|
{
|
||||||
if(cap->flags & CLICAP_FLAGS_STICKY)
|
if(HasCapabilityFlag(cap, CLICAP_FLAGS_STICKY))
|
||||||
{
|
{
|
||||||
finished = 0;
|
finished = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -389,17 +337,11 @@ cap_req(struct Client *source_p, const char *arg)
|
||||||
strcat(pbuf[i], "-");
|
strcat(pbuf[i], "-");
|
||||||
plen++;
|
plen++;
|
||||||
|
|
||||||
capdel |= cap->cap_serv;
|
capdel |= (1 << cap->value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(cap->cap_required_serv && !((capadd & cap->cap_required_serv) == cap->cap_required_serv || IsCapable(source_p, cap->cap_required_serv)))
|
if ((1 << cap->value) == CLICAP_SASL)
|
||||||
{
|
|
||||||
finished = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cap->cap_serv == CLICAP_SASL)
|
|
||||||
{
|
{
|
||||||
struct Client *agent_p = NULL;
|
struct Client *agent_p = NULL;
|
||||||
|
|
||||||
|
@ -417,19 +359,20 @@ cap_req(struct Client *source_p, const char *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
capadd |= cap->cap_serv;
|
capadd |= (1 << cap->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cap->cap_cli)
|
/* XXX this probably should exclude REQACK'd caps from capadd/capdel, but keep old behaviour for now */
|
||||||
|
if(HasCapabilityFlag(cap, CLICAP_FLAGS_REQACK))
|
||||||
{
|
{
|
||||||
strcat(pbuf[i], "~");
|
strcat(pbuf[i], "~");
|
||||||
plen++;
|
plen++;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcat(pbuf[i], cap->name);
|
strcat(pbuf[i], cap->cap);
|
||||||
if (!finished) {
|
if (!finished) {
|
||||||
strcat(pbuf[i], " ");
|
strcat(pbuf[i], " ");
|
||||||
plen += (cap->namelen + 1);
|
plen += (namelen + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue