[MOD] Basic work to get XMPP avatars through PEP

Attaboy!
This commit is contained in:
LDA 2024-09-19 23:24:46 +02:00
commit e54332e376
13 changed files with 428 additions and 25 deletions

View file

@ -40,7 +40,7 @@ static bool
IsPubsubRequest(XMLElement *stanza)
{
char *type = HashMapGet(stanza ? stanza->attrs : NULL, "type");
XMLElement *pubsub, *subscribe;
XMLElement *pubsub;
if (!stanza)
{
return false;
@ -58,7 +58,6 @@ IsPubsubRequest(XMLElement *stanza)
return false;
}
Log(LOG_INFO, "WOAH");
return XMLookForUnique(pubsub, "subscribe");
}

View file

@ -1,5 +1,14 @@
#include "XMPPThread/internal.h"
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Base64.h>
#include <Cytoplasm/Json.h>
#include <Cytoplasm/Log.h>
#include <Cytoplasm/Str.h>
#include <Cytoplasm/Db.h>
#include <string.h>
static char *
SubscriptionHash(ParseeData *data, char *from, char *to)
{
@ -10,14 +19,28 @@ SubscriptionHash(ParseeData *data, char *from, char *to)
len = strlen(from) + 1 + strlen(to);
sum = Malloc(len);
memset(sum, 0x00, len);
memcpy(sum[0], from, strlen(from)):
memcpy(sum[strlen(from) + 1], to, strlen(to));
memcpy(&sum[0], from, strlen(from));
memcpy(&sum[strlen(from) + 1], to, strlen(to));
hash = ParseeHMAC(data->id, sum, len);
hash = Base64Encode(sum, len);
Free(sum);
return hash;
}
static void
DecodeSubscription(ParseeData *data, char *hash, char **from, char **to)
{
char *sum;
if (!data || !hash || !from || !to)
{
return;
}
sum = Base64Decode(hash, strlen(hash));
*from = StrDuplicate(sum);
*to = StrDuplicate(sum + strlen(sum) + 1);
Free(sum);
}
void
AddPresenceSubscriber(ParseeData *data, char *from, char *to)
@ -32,13 +55,18 @@ AddPresenceSubscriber(ParseeData *data, char *from, char *to)
database = data->db;
hash = SubscriptionHash(data, from, to);
ref = DbCreate(database, 2, "subscriptions", hash);
ref = DbCreate(database, 2, "subs", hash);
if (!ref)
{
goto end;
}
HashMapSet(DbRef(ref), "from", JsonValueString(from));
HashMapSet(DbRef(ref), "to", JsonValueString(to));
HashMapSet(DbJson(ref), "from", JsonValueString(from));
HashMapSet(DbJson(ref), "to", JsonValueString(to));
/* I don't think we need more information right now */
DbClose(database, ref);
end:
DbUnlock(database, ref);
Free(hash);
}
@ -48,15 +76,73 @@ IsSubscribed(ParseeData *data, char *user, char *to)
Db *database;
char *hash;
bool ret;
if (!data || !from || !to)
if (!data || !user || !to)
{
return;
return false;
}
database = data->db;
hash = SubscriptionHash(data, from, to);
ret = DbExists(database, 2, "subscriptions", hash);
hash = SubscriptionHash(data, user, to);
ret = DbExists(database, 2, "subs", hash);
Free(hash);
return ret;
}
void
ParseeBroadcastStanza(ParseeData *data, char *from, XMLElement *stanza)
{
XMPPComponent *jabber = data ? data->jabber : NULL;
Array *entries;
size_t i;
if (!data || !from || !stanza)
{
return;
}
/* Copy our stanza so that we can freely modify it */
stanza = XMLCopy(stanza);
/* Start doing a storm on Mt. Subs. */
entries = DbList(data->db, 1, "subs");
for (i = 0; i < ArraySize(entries); i++)
{
char *entry = ArrayGet(entries, i);
char *entry_from = NULL, *entry_to = NULL;
char *storm_id; /* ooe */
XMLElement *sub;
DecodeSubscription(data, entry, &entry_from, &entry_to);
if (!StrEquals(entry_to, from))
{
goto end;
}
Log(LOG_DEBUG,
"PRESENCE SYSTEM: "
"We should be brotkasting straight to %s (from %s)",
entry_from, from
);
sub = XMLCopy(stanza);
XMLAddAttr(sub, "from", from);
XMLAddAttr(sub, "to", entry_from);
/* TODO: Should we store IDs somewhere? */
XMLAddAttr(sub, "id", (storm_id = StrRandom(16)));
pthread_mutex_lock(&jabber->write_lock);
XMLEncode(jabber->stream, sub);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(sub);
Free(storm_id);
end:
Free(entry_from);
Free(entry_to);
}
DbListFree(entries);
XMLFreeElement(stanza);
}

View file

@ -327,6 +327,7 @@ void
IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
{
XMPPComponent *jabber = args->jabber;
XMLElement *pubsub;
char *from = HashMapGet(stanza->attrs, "from");
char *to = HashMapGet(stanza->attrs, "to");
char *id = HashMapGet(stanza->attrs, "id");
@ -395,6 +396,68 @@ IQGet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
XMLFreeElement(iqVCard);
}
}
#define PS "http://jabber.org/protocol/pubsub"
else if ((pubsub = XMLookForTKV(stanza, "pubsub", "xmlns", PS)))
{
/* TODO: Pass this through the PEP manager */
XMLElement *a_items = XMLookForTKV(pubsub,
"items", "node", "urn:xmpp:avatar:data"
);
if (a_items)
{
/* Do, without regret, start shoving an avatar out the bus */
char *to_matrix = ParseeDecodeMXID(to);
char *avatar = ASGetAvatar(args->config, NULL, to_matrix);
char *buf, *mime;
char *b64;
size_t len;
XMLElement *reply;
ASGrab(args->config, avatar, &mime, &buf, &len);
b64 = Base64Encode(buf, len);
Free(buf);
Log(LOG_INFO, "FM=%s", to_matrix);
Log(LOG_INFO, "B=%s (%dB)", b64, (int) len);
/* Strike back with a response */
reply = XMLCreateTag("iq");
XMLAddAttr(reply, "type", "result");
XMLAddAttr(reply, "to", from);
XMLAddAttr(reply, "from", to);
XMLAddAttr(reply, "id", HashMapGet(stanza->attrs, "id"));
{
XMLElement *ps = XMLCreateTag("pubsub");
XMLElement *items = XMLCreateTag("items");
XMLAddAttr(ps, "xmlns", PS);
XMLAddAttr(items, "node", "urn:xmpp:avatar:data");
{
XMLElement *item = XMLCreateTag("item");
XMLElement *data = XMLCreateTag("data");
XMLAddAttr(item, "id", "TODO");
XMLAddAttr(data, "xmlns", "urn:xmpp:avatar:data");
XMLAddChild(data, XMLCreateText(b64));
XMLAddChild(item, data);
XMLAddChild(items, item);
}
XMLAddChild(ps, items);
XMLAddChild(reply, ps);
}
pthread_mutex_lock(&jabber->write_lock);
XMLEncode(jabber->stream, reply);
StreamFlush(jabber->stream);
pthread_mutex_unlock(&jabber->write_lock);
XMLFreeElement(reply);
Free(to_matrix);
Free(avatar);
Free(mime);
Free(b64);
}
}
#undef PS
else if (XMLookForTKV(stanza, "query", "xmlns", DISCO))
{
IQDiscoGet(args, jabber, stanza);

View file

@ -97,6 +97,17 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
Log(LOG_DEBUG, "<message/> usage=%d (%s:%d)", MemoryAllocated(), __FILE__, __LINE__);
return false;
}
/*{
XMLElement *foo = XMLCreateTag("message");
XMLElement *body = XMLCreateTag("body");
XMLAddAttr(foo, "type", "chat");
XMLAddChild(foo, body);
XMLAddChild(body, XMLCreateText("Storm on Mt. Ooe (sorry if you see this)"));
BroadcastStanza(args, HashMapGet(stanza->attrs, "to"), foo);
XMLFreeElement(foo);
}*/
if (ServerHasXEP421(args, from))
{