[ADD/WIP] Bridge media Matrix->XMPP

We're on that Reverse Ideology phase.
This commit is contained in:
LDA 2024-06-27 20:09:52 +02:00
commit fbf169a080
9 changed files with 118 additions and 6 deletions

View file

@ -93,7 +93,7 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
char *user = GrabString(json, 1, "xmpp_user"); char *user = GrabString(json, 1, "xmpp_user");
char *local = ParseeEncodeMXID(sender); char *local = ParseeEncodeMXID(sender);
XMPPSendPlain(jabber, local, user, body, NULL, NULL, NULL, ev_id); XMPPSendPlain(jabber, local, user, body, NULL, NULL, NULL, ev_id, NULL);
Free(local); Free(local);
Free(reply_id); Free(reply_id);
@ -116,6 +116,8 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
char *name = ASGetName(data->config, NULL, sender); char *name = ASGetName(data->config, NULL, sender);
char *rev = StrConcat(3, muc_id, "/", name); char *rev = StrConcat(3, muc_id, "/", name);
char *stanza = NULL, *sender = NULL; char *stanza = NULL, *sender = NULL;
char *url = GrabString(event, 2, "content", "url");
char *unauth = ParseeToUnauth(data, url);
if (reply_id) if (reply_id)
{ {
ParseeGetStanzaInfo(data, chat_id, reply_id, &stanza, &sender); ParseeGetStanzaInfo(data, chat_id, reply_id, &stanza, &sender);
@ -124,12 +126,13 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
XMPPSendPlain( XMPPSendPlain(
jabber, jid, muc_id, jabber, jid, muc_id,
xepd ? xepd : body, "groupchat", xepd ? xepd : body, "groupchat",
stanza, sender, ev_id stanza, sender, ev_id, unauth
); );
Free(rev); Free(rev);
Free(name); Free(name);
Free(stanza); Free(stanza);
Free(sender); Free(sender);
Free(unauth);
} }
Free(chat_id); Free(chat_id);
Free(muc_id); Free(muc_id);

View file

@ -75,6 +75,8 @@ ParseeConfigLoad(char *conf)
CopyToStr(component_host, "component_host"); CopyToStr(component_host, "component_host");
CopyToStr(shared_comp_secret, "shared_secret"); CopyToStr(shared_comp_secret, "shared_secret");
CopyToStr(media_base, "media_base");
CopyToStr(db_path, "db"); CopyToStr(db_path, "db");
JsonFree(json); JsonFree(json);
@ -125,6 +127,7 @@ ParseeConfigFree(void)
Free(config->hs_token); Free(config->hs_token);
Free(config->sender_localpart); Free(config->sender_localpart);
Free(config->namespace_base); Free(config->namespace_base);
Free(config->media_base);
Free(config->listen_as); Free(config->listen_as);
Free(config); Free(config);
} }

View file

@ -602,3 +602,43 @@ end:
DbUnlock(data->db, ref); DbUnlock(data->db, ref);
return ret; return ret;
} }
#include <Cytoplasm/Uri.h>
char *
ParseeToUnauth(ParseeData *data, char *mxc)
{
Uri *url = NULL;
char *ret;
#define PAT "%s/_matrix/client/v1/media/download/%s%s"
size_t l;
if (!data || !mxc)
{
return NULL;
}
url = UriParse(mxc);
if (!url)
{
Log(LOG_ERR, "cant parse %s", mxc);
return NULL;
}
if (!StrEquals(url->proto, "mxc"))
{
UriFree(url);
return NULL;
}
/* TODO: HTTPS */
l = snprintf(NULL, 0,
PAT,
data->config->media_base,
url->host, url->path
);
ret = Malloc(l + 3);
snprintf(ret, l + 1,
PAT,
data->config->media_base,
url->host, url->path
);
UriFree(url);
return ret;
}

49
src/Routes/Media.c Normal file
View file

@ -0,0 +1,49 @@
#include <Routes.h>
#include <Cytoplasm/Memory.h>
#include <Cytoplasm/Str.h>
#include <Matrix.h>
#include <Parsee.h>
#include <AS.h>
RouteHead(RouteMedia, arr, argp)
{
ParseeHttpArg *args = argp;
HttpClientContext *cctx;
HashMap *reqh;
char *server = ArrayGet(arr, 0);
char *identi = ArrayGet(arr, 1);
char *path, *key, *val;
/* TODO: Make it check the DB for its validicity. "Purging" would be useful.
*/
if (!server || !identi)
{
HttpResponseStatus(args->ctx, HTTP_BAD_REQUEST);
return MatrixCreateError("M_NOT_YET_UPLOADED", "No server/identifier");
}
server = HttpUrlEncode(server);
identi = HttpUrlEncode(identi);
path = StrConcat(4, "/_matrix/media/v3/download/", server, "/", identi);
cctx = ParseeCreateRequest(args->data->config, HTTP_GET, path);
ASAuthenticateRequest(args->data->config, cctx);
Free(path);
HttpRequestSendHeaders(cctx);
HttpRequestSend(cctx);
reqh = HttpResponseHeaders(cctx);
while (HashMapIterate(reqh, &key, (void **) &val))
{
HttpResponseHeader(args->ctx, key, val);
}
HttpSendHeaders(args->ctx);
StreamCopy(HttpClientStream(cctx), HttpServerStream(args->ctx));
HttpClientContextFree(cctx);
Free(server);
Free(identi);
return NULL;
}

View file

@ -8,7 +8,7 @@
#include <XML.h> #include <XML.h>
void void
XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id) XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob)
{ {
XMLElement *message, *body, *data, *parsee; XMLElement *message, *body, *data, *parsee;
char *from; char *from;
@ -25,7 +25,7 @@ XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, ch
XMLAddAttr(message, "type", type); XMLAddAttr(message, "type", type);
body = XMLCreateTag("body"); body = XMLCreateTag("body");
data = XMLCreateText(msg); data = XMLCreateText(oob ? oob : msg);
/* TODO: Add Parsee specific fields here */ /* TODO: Add Parsee specific fields here */
parsee = XMLCreateTag("x-parsee"); parsee = XMLCreateTag("x-parsee");
@ -65,6 +65,18 @@ XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, ch
/* TODO: Add custom fields depending on the caller's wishes */ /* TODO: Add custom fields depending on the caller's wishes */
} }
if (oob)
{
XMLElement *xoob, *oob_data, *oob_url;
xoob = XMLCreateTag("x");
XMLAddAttr(xoob, "xmlns", "jabber:x:oob");
oob_url = XMLCreateTag("url");
oob_data = XMLCreateText(oob);
XMLAddChild(oob_url, oob_data);
XMLAddChild(xoob, oob_url);
XMLAddChild(message, xoob);
}
if (rst && rse) if (rst && rse)
{ {
int off = ParseeFindDatastart(msg); int off = ParseeFindDatastart(msg);

View file

@ -208,6 +208,7 @@ IQDiscoGet(ParseeData *args, XMPPComponent *jabber, XMLElement *stanza)
AdvertiseSimple("urn:xmpp:styling:0"); AdvertiseSimple("urn:xmpp:styling:0");
AdvertiseSimple("urn:xmpp:reply:0"); AdvertiseSimple("urn:xmpp:reply:0");
AdvertiseSimple("urn:xmpp:sid:0"); AdvertiseSimple("urn:xmpp:sid:0");
AdvertiseSimple("jabber:x:oob");
AdvertiseSimple("urn:parsee:x-parsee:0"); AdvertiseSimple("urn:parsee:x-parsee:0");
AdvertiseSimple("urn:parsee:jealousy:0"); AdvertiseSimple("urn:parsee:jealousy:0");

View file

@ -19,6 +19,7 @@ typedef struct ParseeConfig {
char *namespace_base; char *namespace_base;
char *listen_as; char *listen_as;
char *media_base;
int port; int port;
/* Homeserver port info */ /* Homeserver port info */
@ -171,4 +172,6 @@ extern char * ParseeXMPPify(HashMap *event);
/* Finds an event ID from an ID in the stanza's attributes */ /* Finds an event ID from an ID in the stanza's attributes */
extern char * ParseeEventFromID(ParseeData *d, char *c_id, char *ori_id); extern char * ParseeEventFromID(ParseeData *d, char *c_id, char *ori_id);
extern char * ParseeEventFromSID(ParseeData *d, char *c_id, char *ori_id); extern char * ParseeEventFromSID(ParseeData *d, char *c_id, char *ori_id);
extern char * ParseeToUnauth(ParseeData *data, char *mxc);
#endif #endif

View file

@ -13,7 +13,8 @@ typedef struct ParseeHttpArg {
X_ROUTE("/_matrix/app/v1/transactions/(.*)", RouteTxns) \ X_ROUTE("/_matrix/app/v1/transactions/(.*)", RouteTxns) \
X_ROUTE("/_matrix/app/v1/ping", RoutePing) \ X_ROUTE("/_matrix/app/v1/ping", RoutePing) \
X_ROUTE("/_matrix/app/v1/users/(.*)", RouteUserAck) \ X_ROUTE("/_matrix/app/v1/users/(.*)", RouteUserAck) \
X_ROUTE("/_matrix/app/v1/rooms/(.*)", RouteRoomAck) X_ROUTE("/_matrix/app/v1/rooms/(.*)", RouteRoomAck) \
X_ROUTE("/_matrix/client/v1/media/download/(.*)/(.*)", RouteMedia)
#define X_ROUTE(path, name) extern void * name(Array *, void *); #define X_ROUTE(path, name) extern void * name(Array *, void *);
ROUTES ROUTES

View file

@ -28,7 +28,7 @@ extern bool XMPPAuthenticateCompStream(XMPPComponent *comp, char *shared);
extern void XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc); extern void XMPPJoinMUC(XMPPComponent *comp, char *fr, char *muc);
/* TODO: XMPP stuff, I don't fucking know, I'm not a Jabbernerd. */ /* TODO: XMPP stuff, I don't fucking know, I'm not a Jabbernerd. */
extern void XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id); extern void XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob);
/* Closes a raw component stream. */ /* Closes a raw component stream. */
extern void XMPPEndCompStream(XMPPComponent *stream); extern void XMPPEndCompStream(XMPPComponent *stream);