/* modules/m_cap.c
- *
+ *
* Copyright (C) 2005 Lee Hardy <lee@leeh.co.uk>
* Copyright (C) 2005 ircd-ratbox development team
*
#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 *);
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
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("extended-join", CLICAP_EXTENDED_JOIN, 0, 0),
- _CLICAP("away-notify", CLICAP_AWAY_NOTIFY, 0, 0),
+ _CLICAP("multi-prefix", CLICAP_MULTI_PREFIX, 0, 0, 0),
+ _CLICAP("sasl", CLICAP_SASL, 0, 0, 0),
+ _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),
};
#define CLICAP_LIST_LEN (sizeof(clicap_list) / sizeof(struct clicap))
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)
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;
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)
{
buflen++;
/* needs a client ack */
- if(clicap_list[i].cap_cli &&
+ if(clicap_list[i].cap_cli &&
IsCapable(source_p, clicap_list[i].cap_cli))
{
*p++ = '~';
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 */
}
else
{
+ if(cap->cap_required_serv && !((capadd & cap->cap_required_serv) == cap->cap_required_serv || IsCapable(source_p, cap->cap_required_serv)))
+ {
+ 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;
+ }
+ }
+
if(cap->flags & CLICAP_FLAGS_STICKY)
{
strcat(pbuf[i], "=");