[MOD] Start not hardcoding discovery features

The eventual goal here is to have different disco replies for specific
kinds of JID, effectively allowing us to have MUCs. Yeah.
This commit is contained in:
LDA 2024-11-29 13:58:49 +01:00
commit 2e566c73fc
6 changed files with 148 additions and 66 deletions

View file

@ -8,6 +8,8 @@
#include <Parsee.h>
#include <XML.h>
#include "XMPPThread/internal.h"
bool
XMPPQueryMUC(XMPPComponent *jabber, char *muc, MUCInfo *out)
{
@ -162,6 +164,7 @@ bool
XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int time, bool ret)
{
XMLElement *presence, *x, *reply, *history, *photo;
IQFeatures *features;
char *from, *id, *stime = "3600";
if (!comp || !fr || !muc)
{
@ -189,7 +192,15 @@ XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc, char *hash, int time, bool
XMLAddChild(x, history);
XMLAddChild(presence, x);
XMPPAnnotatePresence(presence);
features = CreateIQFeatures();
#define IdentitySimple(cat, Type, Name) AddIQIdentity(features, cat, NULL, Type, Name);
IQ_IDENTITY
#undef IdentitySimple
#define AdvertiseSimple(feature) AdvertiseIQFeature(features, feature);
IQ_ADVERT
#undef AdvertiseSimple
XMPPAnnotatePresence(presence, features);
FreeIQFeatures(features);
if (hash)
{
@ -225,6 +236,7 @@ void
XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *reason)
{
XMLElement *presence;
IQFeatures *features;
char *from, *id;
if (!comp || !fr || !muc)
{
@ -246,7 +258,16 @@ XMPPLeaveMUC(XMPPComponent *comp, char *fr, char *muc, char *reason)
XMLAddChild(presence, status);
}
XMPPAnnotatePresence(presence);
features = CreateIQFeatures();
#define IdentitySimple(cat, Type, Name) AddIQIdentity(features, cat, NULL, Type, Name);
IQ_IDENTITY
#undef IdentitySimple
#define AdvertiseSimple(feature) AdvertiseIQFeature(features, feature);
IQ_ADVERT
#undef AdvertiseSimple
XMPPAnnotatePresence(presence, features);
FreeIQFeatures(features);
XMPPSendStanza(comp, presence, 10000);

View file

@ -159,27 +159,6 @@ XMPPGetReply(XMLElement *elem)
return HashMapGet(rep->attrs, "id");
}
void
XMPPAnnotatePresence(XMLElement *presence)
{
XMLElement *c;
char *ver;
if (!presence)
{
return;
}
ver = XMPPGenerateVer();
c = XMLCreateTag("c");
XMLAddAttr(c, "xmlns", "http://jabber.org/protocol/caps");
XMLAddAttr(c, "hash", "sha-1");
XMLAddAttr(c, "node", REPOSITORY);
XMLAddAttr(c, "ver", ver);
Free(ver);
XMLAddChild(presence, c);
}
char *
XMPPGetModeration(XMLElement *stanza)
{

View file

@ -12,33 +12,86 @@
#include "XMPPThread/internal.h"
IQFeatures *
CreateIQFeatures(void)
{
IQFeatures *ret = Malloc(sizeof(*ret));
ret->identity = ArrayCreate();
ret->adverts = ArrayCreate();
return ret;
}
void
FreeIQFeatures(IQFeatures *features)
{
size_t i;
if (!features)
{
return;
}
for (i = 0; i < ArraySize(features->adverts); i++)
{
Free(ArrayGet(features->adverts, i));
}
ArrayFree(features->adverts);
for (i = 0; i < ArraySize(features->identity); i++)
{
XMPPIdentity *identity = ArrayGet(features->identity, i);
Free(identity->category);
Free(identity->type);
Free(identity->lang);
Free(identity->name);
Free(identity);
}
ArrayFree(features->identity);
Free(features);
}
void
AdvertiseIQFeature(IQFeatures *f, char *feature)
{
if (!f || !feature)
{
return;
}
ArrayAdd(f->adverts, StrDuplicate(feature));
}
void
AddIQIdentity(IQFeatures *f, char *cat, char *lang, char *type, char *name)
{
XMPPIdentity *identity;
if (!f)
{
return;
}
identity = Malloc(sizeof(*identity));
identity->category = StrDuplicate(cat);
identity->type = StrDuplicate(type);
identity->lang = StrDuplicate(lang);
identity->name = StrDuplicate(name);
ArrayAdd(f->identity, identity);
}
/* Generates a SHA-256 hash of the ver field. */
char *
XMPPGenerateVer(void)
XMPPGenerateVer(IQFeatures *features)
{
char *S = NULL;
unsigned char *Sha = NULL;
Array *identities = ArrayCreate();
Array *features = ArrayCreate();
size_t i;
/* Initialise identity table, to be sorted */
#define IdentitySimple(cat, Type, Name) { \
XMPPIdentity *id = Malloc(sizeof(*id)); \
id->category = cat; \
id->lang = NULL; \
id->type = Type; \
id->name = Name; \
ArrayAdd(identities, id); }
IQ_IDENTITY
#undef IdentitySimple
#define AdvertiseSimple(feature) ArrayAdd(features, feature);
IQ_ADVERT
#undef AdvertiseSimple
ArraySort(identities, IdentitySort);
for (i = 0; i < ArraySize(identities); i++)
ArraySort(features->identity, IdentitySort);
for (i = 0; i < ArraySize(features->identity); i++)
{
XMPPIdentity *identity = ArrayGet(identities, i);
XMPPIdentity *identity = ArrayGet(features->identity, i);
char *id_chunk = StrConcat(7,
identity->category, "/",
identity->type, "/",
@ -50,10 +103,10 @@ XMPPGenerateVer(void)
Free(id_chunk);
}
ArraySort(features, ((int (*) (void *, void *)) ICollate));
for (i = 0; i < ArraySize(features); i++)
ArraySort(features->adverts, ((int (*) (void *, void *)) ICollate));
for (i = 0; i < ArraySize(features->adverts); i++)
{
char *feature = ArrayGet(features, i);
char *feature = ArrayGet(features->adverts, i);
char *tmp = S;
S = StrConcat(3, S, feature, "<");
Free(tmp);
@ -64,16 +117,28 @@ XMPPGenerateVer(void)
S = Base64Encode((const char *) Sha, 20);
Free(Sha);
ArrayFree(features);
for (i = 0; i < ArraySize(identities); i++)
{
XMPPIdentity *identity = ArrayGet(identities, i);
/* We don't have to do anything here. */
Free(identity);
}
ArrayFree(identities);
return S;
}
void
XMPPAnnotatePresence(XMLElement *presence, IQFeatures *features)
{
XMLElement *c;
char *ver;
if (!presence || !features)
{
return;
}
ver = XMPPGenerateVer(features);
c = XMLCreateTag("c");
XMLAddAttr(c, "xmlns", "http://jabber.org/protocol/caps");
XMLAddAttr(c, "hash", "sha-1");
XMLAddAttr(c, "node", REPOSITORY);
XMLAddAttr(c, "ver", ver);
Free(ver);
XMLAddChild(presence, c);
}

View file

@ -151,6 +151,7 @@ IQDiscoGet(ParseeData *args, XMPPComponent *jabber, XMLElement *stanza)
{
char *from, *to, *id;
XMLElement *iq_reply, *query;
IQFeatures *features = CreateIQFeatures();
from = HashMapGet(stanza->attrs, "from");
to = HashMapGet(stanza->attrs, "to");
@ -164,8 +165,14 @@ IQDiscoGet(ParseeData *args, XMPPComponent *jabber, XMLElement *stanza)
XMLAddAttr(iq_reply, "id", id);
query = IQGenerateQuery();
#define IdentitySimple(cat, Type, Name) AddIQIdentity(features, cat, NULL, Type, Name);
IQ_IDENTITY
#undef IdentitySimple
#define AdvertiseSimple(feature) AdvertiseIQFeature(features, feature);
IQ_ADVERT
#undef AdvertiseSimple
{
char *ver = XMPPGenerateVer();
char *ver = XMPPGenerateVer(features);
char *node = StrConcat(3, REPOSITORY, "#", ver);
XMLAddAttr(query, "node", node);
@ -173,6 +180,7 @@ IQDiscoGet(ParseeData *args, XMPPComponent *jabber, XMLElement *stanza)
Free(ver);
}
XMLAddChild(iq_reply, query);
FreeIQFeatures(features);
XMPPSendStanza(jabber, iq_reply, args->config->max_stanza_size);
XMLFreeElement(iq_reply);

View file

@ -32,13 +32,17 @@
IdentitySimple("client", "pc", NAME " v" VERSION " bridge") \
IdentitySimple("component", "generic", "Parsee's component")
typedef struct PEPManager PEPManager;
typedef void (*PEPEvent)(PEPManager *m, XMLElement *stanza, XMLElement *item);
typedef struct IQFeatures {
Array *identity;
Array *adverts;
} IQFeatures;
typedef struct XMPPIdentity {
char *category, *type, *lang, *name;
} XMPPIdentity;
typedef struct PEPManager PEPManager;
typedef void (*PEPEvent)(PEPManager *m, XMLElement *stanza, XMLElement *item);
typedef struct XMPPThread XMPPThread;
typedef struct XMPPThreadInfo {
/* A FIFO of stanzas inbound, to be read by dispatcher
@ -65,6 +69,21 @@ struct XMPPThread {
int ICollate(unsigned char *cata, unsigned char *catb);
int IdentitySort(void *idap, void *idbp);
IQFeatures * CreateIQFeatures(void);
void AddIQIdentity(IQFeatures *, char *category, char *lang, char *type, char *name);
void AdvertiseIQFeature(IQFeatures *, char *feature);
void FreeIQFeatures(IQFeatures *);
/** Generate the B64-encoded SHA-256 hash for the 'ver' field in caps.
* --------
* Returns: A base64 encoded ver hash[LA:HEAP]
* Modifies: NOTHING
* See-Also: https://xmpp.org/extensions/xep-0115.html */
char * XMPPGenerateVer(IQFeatures *features);
/* Annotates a presence with https://xmpp.org/extensions/xep-0115.html */
void XMPPAnnotatePresence(XMLElement *presence, IQFeatures *features);
char * ParseeGetBridgedRoom(ParseeData *data, XMLElement *stanza);
char * ParseeGetEventFromID(ParseeData *data, XMLElement *stanza, char *id);
char * ParseeGetReactedEvent(ParseeData *data, XMLElement *stanza);

View file

@ -98,16 +98,6 @@ extern char * XMPPGetReply(XMLElement *elem);
* See-Also: https://xmpp.org/extensions/xep-0425.html */
extern char * XMPPGetModeration(XMLElement *stanza);
/** Generate the B64-encoded SHA-256 hash for the 'ver' field in caps.
* --------
* Returns: A base64 encoded ver hash[LA:HEAP]
* Modifies: NOTHING
* See-Also: https://xmpp.org/extensions/xep-0115.html */
extern char * XMPPGenerateVer(void);
/* Annotates a presence with https://xmpp.org/extensions/xep-0115.html */
extern void XMPPAnnotatePresence(XMLElement *presence);
extern bool XMPPHasError(XMLElement *stanza, char *type);
#include <Parsee.h>