mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 15:15:10 +00:00
[ADD/WIP] VCard4, slightly more PEPwerk
This commit is contained in:
parent
3c495a8a81
commit
ee004ca9c0
10 changed files with 313 additions and 32 deletions
|
|
@ -881,3 +881,18 @@ ParseeAchievement(const char *func, const char *msg, bool die)
|
|||
abort();
|
||||
}
|
||||
}
|
||||
char *
|
||||
ParseeGenerateMTO(char *common_id)
|
||||
{
|
||||
char *matrix_to;
|
||||
if (!common_id)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
common_id = HttpUrlEncode(common_id);
|
||||
matrix_to = StrConcat(2, "https://matrix.to/#/", common_id);
|
||||
Free(common_id);
|
||||
|
||||
return matrix_to;
|
||||
}
|
||||
|
|
|
|||
126
src/XMPPThread/PEP.c
Normal file
126
src/XMPPThread/PEP.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
#include "XMPPThread/internal.h"
|
||||
|
||||
#include <Cytoplasm/HashMap.h>
|
||||
#include <Cytoplasm/Memory.h>
|
||||
#include <Cytoplasm/Str.h>
|
||||
#include <Cytoplasm/Log.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
struct PEPManager {
|
||||
pthread_mutex_t lock;
|
||||
|
||||
ParseeData *data;
|
||||
HashMap *node_table;
|
||||
|
||||
void *cookie;
|
||||
};
|
||||
|
||||
PEPManager *
|
||||
CreatePEPManager(ParseeData *data, void *cookie)
|
||||
{
|
||||
PEPManager *ret;
|
||||
if (!data)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = Malloc(sizeof(*ret));
|
||||
ret->cookie = cookie;
|
||||
ret->data = data;
|
||||
ret->node_table = HashMapCreate();
|
||||
pthread_mutex_init(&ret->lock, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
void *
|
||||
PEPManagerCookie(PEPManager *manager)
|
||||
{
|
||||
return manager ? manager->cookie : NULL;
|
||||
}
|
||||
void
|
||||
PEPManagerAddEvent(PEPManager *manager, char *node, PEPEvent event)
|
||||
{
|
||||
if (!manager || !node || !event)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&manager->lock);
|
||||
HashMapSet(manager->node_table, node, event);
|
||||
pthread_mutex_unlock(&manager->lock);
|
||||
}
|
||||
|
||||
static bool
|
||||
PEPManagerHandleEvent(PEPManager *manager, XMLElement *stanza)
|
||||
{
|
||||
PEPEvent call = NULL;
|
||||
XMLElement *event, *ps, *ev;
|
||||
size_t i;
|
||||
if (!manager || !stanza)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#define PEP_NS "http://jabber.org/protocol/pubsub"
|
||||
if (!(ps = XMLookForTKV(stanza, "pubsub", "xmlns", PEP_NS)) &&
|
||||
!(ev = XMLookForTKV(stanza, "event", "xmlns", PEP_NS "#event")))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
event = ps ? ps : ev;
|
||||
|
||||
for (i = 0; i < ArraySize(event->children); i++)
|
||||
{
|
||||
XMLElement *items = ArrayGet(event->children, i);
|
||||
char *node = HashMapGet(items->attrs, "node");
|
||||
|
||||
if ((call = HashMapGet(manager->node_table, node)))
|
||||
{
|
||||
size_t j;
|
||||
/* Use the callback over all items */
|
||||
if (ev)
|
||||
{
|
||||
for (j = 0; j < ArraySize(items->children); j++)
|
||||
{
|
||||
call(manager, stanza, ArrayGet(items->children, j));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ... or over "items" specifically. */
|
||||
call(manager, stanza, items);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PEPManagerHandle(PEPManager *manager, XMLElement *stanza)
|
||||
{
|
||||
if (!manager || !stanza)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check if it is a PEP stanza */
|
||||
if (PEPManagerHandleEvent(manager, stanza))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
void
|
||||
DestroyPEPManager(PEPManager *manager)
|
||||
{
|
||||
if (!manager)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&manager->lock);
|
||||
HashMapFree(manager->node_table);
|
||||
Free(manager);
|
||||
}
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
#include "XMPPThread/internal.h"
|
||||
|
||||
#include <Cytoplasm/Memory.h>
|
||||
#include <Cytoplasm/Json.h>
|
||||
#include <Cytoplasm/Str.h>
|
||||
|
||||
#include <Parsee.h>
|
||||
#include <XMPP.h>
|
||||
#include <XML.h>
|
||||
|
||||
/* Manages an avatar metadata pubsub item */
|
||||
#include <Cytoplasm/Memory.h>
|
||||
#include <Cytoplasm/Json.h>
|
||||
#include <Cytoplasm/Str.h>
|
||||
#include <Cytoplasm/Log.h>
|
||||
#include <Cytoplasm/Db.h>
|
||||
|
||||
static XMLElement *
|
||||
CreateAvatarRequest(char *from, char *to, char *avatar_id)
|
||||
{
|
||||
|
|
@ -38,9 +39,11 @@ CreateAvatarRequest(char *from, char *to, char *avatar_id)
|
|||
|
||||
|
||||
void
|
||||
ManageProfileItem(ParseeData *args, XMLElement *item, XMLElement *stanza, XMPPThread *thr)
|
||||
PEPAvatarEvent(PEPManager *m, XMLElement *stanza, XMLElement *item)
|
||||
{
|
||||
XMPPComponent *jabber = args->jabber;
|
||||
XMPPThreadInfo *info = PEPManagerCookie(m);
|
||||
XMPPComponent *jabber = info->jabber;
|
||||
ParseeData *args = info->args;
|
||||
DbRef *avatars;
|
||||
HashMap *json;
|
||||
|
||||
|
|
@ -82,4 +85,3 @@ ManageProfileItem(ParseeData *args, XMLElement *item, XMLElement *stanza, XMPPTh
|
|||
end:
|
||||
DbUnlock(args->db, avatars);
|
||||
}
|
||||
|
||||
116
src/XMPPThread/PEPs/VCard.c
Normal file
116
src/XMPPThread/PEPs/VCard.c
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#include "XMPPThread/internal.h"
|
||||
|
||||
#include <Parsee.h>
|
||||
#include <XMPP.h>
|
||||
#include <XML.h>
|
||||
#include <AS.h>
|
||||
|
||||
#include <Cytoplasm/Memory.h>
|
||||
#include <Cytoplasm/Str.h>
|
||||
#include <Cytoplasm/Log.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define AddFieldBase(type) \
|
||||
XMLElement *field, *text, *text_data; \
|
||||
field = XMLCreateTag(name); \
|
||||
text = XMLCreateTag(type); \
|
||||
text_data = XMLCreateText(value); \
|
||||
\
|
||||
XMLAddChild(vcard, field); \
|
||||
XMLAddChild(field, text); \
|
||||
XMLAddChild(text, text_data)
|
||||
static void
|
||||
AddTextField(XMLElement *vcard, char *name, char *value)
|
||||
{
|
||||
AddFieldBase("text");
|
||||
}
|
||||
static void
|
||||
AddURIField(XMLElement *vcard, char *name, char *value)
|
||||
{
|
||||
AddFieldBase("uri");
|
||||
}
|
||||
#undef AddFieldBase
|
||||
|
||||
void
|
||||
PEPVCardEvent(PEPManager *m, XMLElement *stanza, XMLElement *item)
|
||||
{
|
||||
XMPPThreadInfo *info = PEPManagerCookie(m);
|
||||
XMPPComponent *jabber = info->jabber;
|
||||
ParseeData *data = info->args;
|
||||
char *from = HashMapGet(stanza->attrs, "from");
|
||||
char *to = HashMapGet(stanza->attrs, "to");
|
||||
char *id = HashMapGet(stanza->attrs, "id");
|
||||
XMLElement *reply;
|
||||
|
||||
reply = XMLCreateTag("iq");
|
||||
XMLAddAttr(reply, "type", "result");
|
||||
XMLAddAttr(reply, "id", id);
|
||||
XMLAddAttr(reply, "from", to);
|
||||
XMLAddAttr(reply, "to", from);
|
||||
{
|
||||
XMLElement *pubsub, *items, *item;
|
||||
pubsub = XMLCreateTag("pubsub");
|
||||
items = XMLCreateTag("items");
|
||||
item = XMLCreateTag("item");
|
||||
XMLAddChild(reply, pubsub);
|
||||
XMLAddChild(pubsub, items);
|
||||
XMLAddChild(items, item);
|
||||
XMLAddAttr(pubsub, "xmlns", "http://jabber.org/protocol/pubsub");
|
||||
XMLAddAttr(items, "node", "urn:xmpp:vcard4");
|
||||
{
|
||||
XMLElement *vcard = XMLCreateTag("vcard");
|
||||
XMLAddAttr(vcard, "xmlns", "urn:ietf:params:xml:ns:vcard-4.0");
|
||||
|
||||
if (!strncmp(to, "parsee", 6))
|
||||
{
|
||||
AddTextField(vcard, "title", "System user");
|
||||
|
||||
AddTextField(vcard, "fn", "Parsee Mizuhashi");
|
||||
AddTextField(vcard, "nickname", "parsee");
|
||||
AddTextField(vcard, "nickname", "that annoying bridge");
|
||||
AddTextField(vcard, "nickname", "green-eyed monster");
|
||||
|
||||
AddURIField(vcard, "url", REPOSITORY);
|
||||
AddURIField(vcard, "url", "https://kappach.at/parsee");
|
||||
|
||||
AddTextField(vcard, "note", "This is the Parsee user account.");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* TODO: Get the user's info(over the Matrix profile API if
|
||||
* the server shows support for it.) */
|
||||
char *mxid = ParseeDecodeMXID(to);
|
||||
char *name = ASGetName(data->config, NULL, mxid);
|
||||
char *m_to = ParseeGenerateMTO(mxid);
|
||||
|
||||
AddTextField(vcard, "title", "Matrix user");
|
||||
|
||||
AddTextField(vcard, "fn", name);
|
||||
AddTextField(vcard, "nickname", mxid);
|
||||
|
||||
AddURIField(vcard, "url", REPOSITORY);
|
||||
AddURIField(vcard, "url", "https://kappach.at/parsee");
|
||||
AddURIField(vcard, "url", "https://matrix.org");
|
||||
AddURIField(vcard, "url", m_to);
|
||||
|
||||
AddTextField(
|
||||
vcard,
|
||||
"note",
|
||||
"This is a bridged Matrix user, from Parsee."
|
||||
);
|
||||
Free(mxid);
|
||||
Free(name);
|
||||
Free(m_to);
|
||||
}
|
||||
|
||||
XMLAddChild(item, vcard);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&jabber->write_lock);
|
||||
XMLEncode(jabber->stream, reply);
|
||||
StreamFlush(jabber->stream);
|
||||
pthread_mutex_unlock(&jabber->write_lock);
|
||||
XMLFreeElement(reply);
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
#include <XMPP.h>
|
||||
#include <XML.h>
|
||||
|
||||
/* TODO: This should be in PEP.c */
|
||||
XMLElement *
|
||||
CreatePubsubRequest(char *from, char *to, char *node)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ ParseeXMPPThread(void *argp)
|
|||
/* Initialise the await table */
|
||||
await_table = HashMapCreate();
|
||||
|
||||
/* Initialise the command manager, and add all ad-hoc commands */
|
||||
/* Initialise the managers, and add all handlers. */
|
||||
info.m = XMPPCreateManager(args);
|
||||
{
|
||||
XMPPCommand *cmd;
|
||||
|
|
@ -137,6 +137,17 @@ ParseeXMPPThread(void *argp)
|
|||
XMPPCOMMANDS
|
||||
#undef XMPP_COMMAND
|
||||
}
|
||||
info.pep_manager = CreatePEPManager(args, &info);
|
||||
{
|
||||
PEPManagerAddEvent(
|
||||
info.pep_manager,
|
||||
"urn:xmpp:avatar:metadata", PEPAvatarEvent
|
||||
);
|
||||
PEPManagerAddEvent(
|
||||
info.pep_manager,
|
||||
"urn:xmpp:vcard4", PEPVCardEvent
|
||||
);
|
||||
}
|
||||
|
||||
/* Initialise the FIFO */
|
||||
info.stanzas = ArrayCreate();
|
||||
|
|
@ -221,6 +232,7 @@ ParseeXMPPThread(void *argp)
|
|||
|
||||
pthread_mutex_destroy(&info.lock);
|
||||
|
||||
DestroyPEPManager(info.pep_manager);
|
||||
XMPPFreeManager(info.m);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,8 @@ IQResult(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
|||
{
|
||||
XMLElement *vcard = XMLookForTKV(stanza, "vCard", "xmlns", "vcard-temp");
|
||||
|
||||
|
||||
/* TODO: Move this to PEP */
|
||||
XMLElement *event = XMLookForTKV(stanza, "pubsub",
|
||||
"xmlns", "http://jabber.org/protocol/pubsub"
|
||||
);
|
||||
|
|
@ -425,10 +427,15 @@ IQSet(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
|||
}
|
||||
#undef DISCO
|
||||
|
||||
void IQStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||
void
|
||||
IQStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||
{
|
||||
char *type;
|
||||
type = HashMapGet(stanza->attrs, "type");
|
||||
char *type = HashMapGet(stanza->attrs, "type");
|
||||
|
||||
if (PEPManagerHandle(thr->info->pep_manager, stanza))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#define OnType(ctyp, callback) do \
|
||||
{ \
|
||||
if (StrEquals(type, #ctyp)) \
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
|||
XMLElement *reactions = NULL;
|
||||
XMLElement *body = NULL;
|
||||
XMLElement *data = NULL;
|
||||
XMLElement *event = NULL;
|
||||
|
||||
char *to, *room, *from, *from_matrix, *decode_from;
|
||||
char *mroom_id = NULL;
|
||||
|
|
@ -64,25 +63,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
|||
}
|
||||
body = XMLookForUnique(stanza, "body");
|
||||
|
||||
event = XMLookForTKV(stanza, "event",
|
||||
"xmlns", "http://jabber.org/protocol/pubsub#event"
|
||||
);
|
||||
if (event)
|
||||
{
|
||||
size_t i;
|
||||
XMLElement *items =
|
||||
XMLookForTKV(event, "items", "node", "urn:xmpp:avatar:metadata");
|
||||
if (items)
|
||||
{
|
||||
for (i = 0; i < ArraySize(items->children); i++)
|
||||
{
|
||||
ManageProfileItem(
|
||||
args, ArrayGet(items->children, i),
|
||||
stanza, thr
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
PEPManagerHandle(thr->info->pep_manager, stanza);
|
||||
|
||||
#define CHAT_STATES "http://jabber.org/protocol/chatstates"
|
||||
if (XMLookForTKV(stanza, "composing", "xmlns", CHAT_STATES))
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@
|
|||
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 XMPPIdentity {
|
||||
char *category, *type, *lang, *name;
|
||||
} XMPPIdentity;
|
||||
|
|
@ -46,6 +49,7 @@ typedef struct XMPPThreadInfo {
|
|||
ParseeData *args;
|
||||
XMPPComponent *jabber;
|
||||
XMPPCommandManager *m;
|
||||
PEPManager *pep_manager;
|
||||
|
||||
struct XMPPThread *dispatchers;
|
||||
size_t available_dispatchers;
|
||||
|
|
@ -80,3 +84,13 @@ bool ServerHasXEP421(ParseeData *data, char *from);
|
|||
|
||||
char * ParseeGetBridgedUserI(ParseeData *data, XMLElement *stanza, char *force);
|
||||
#define ParseeGetBridgedUser(data, stanza) ParseeGetBridgedUserI(data, stanza, NULL)
|
||||
|
||||
PEPManager * CreatePEPManager(ParseeData *data, void *cookie);
|
||||
void * PEPManagerCookie(PEPManager *manager);
|
||||
void PEPManagerAddEvent(PEPManager *manager, char *node, PEPEvent event);
|
||||
bool PEPManagerHandle(PEPManager *manager, XMLElement *stanza);
|
||||
void DestroyPEPManager(PEPManager *manager);
|
||||
|
||||
/* PEP callbacks for the handler */
|
||||
void PEPAvatarEvent(PEPManager *m, XMLElement *stanza, XMLElement *item);
|
||||
void PEPVCardEvent(PEPManager *m, XMLElement *stanza, XMLElement *item);
|
||||
|
|
|
|||
|
|
@ -255,4 +255,11 @@ extern char * ParseeMXID(ParseeData *data);
|
|||
extern void ParseeAchievement(const char *func, const char *msg, bool die);
|
||||
#define Achievement(msg, die) ParseeAchievement(__func__, msg, die)
|
||||
|
||||
/** Generates a 'matrix.to' URL from a Matrix ID, to be used for
|
||||
* linking to a room, user, etc...
|
||||
* ----------------------
|
||||
* Returns: A Matrix URL[LA:HEAP]
|
||||
* Thrasher: Free */
|
||||
extern char * ParseeGenerateMTO(char *common_id);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue