From e2b014d00056d8e39a5c277e8d286249a16d44e9 Mon Sep 17 00:00:00 2001 From: lda Date: Sat, 15 Feb 2025 08:44:25 +0000 Subject: [PATCH] [FIX/WIP] Fix replies and try fixing a bug with MUCs --- src/AS/Room.c | 18 +++++++++-- src/Main.c | 1 + src/MatrixEventHandler.c | 4 +-- src/Parsee/User.c | 51 ++++++++++++++++++++++++-------- src/Unistr.c | 35 ++++++++++++++++++++++ src/XMPP/Stanza.c | 25 ++++++++++++++++ src/XMPPThread/Stanzas/Message.c | 14 ++++++++- src/include/Parsee.h | 2 +- src/include/Routes.h | 3 +- src/include/Unistring.h | 6 ++++ src/include/XMPP.h | 3 ++ 11 files changed, 142 insertions(+), 20 deletions(-) diff --git a/src/AS/Room.c b/src/AS/Room.c index 9e10579..e9691e1 100644 --- a/src/AS/Room.c +++ b/src/AS/Room.c @@ -25,11 +25,13 @@ ASInvite(const ParseeConfig *conf, char *id, char *invited) "@", conf->sender_localpart, ":", conf->server_base ); + id = HttpUrlEncode(id); path = StrConcat(5, "/_matrix/client/v3/rooms/", id, "/invite", "?user_id=", bridge ); Free(bridge); + Free(id); ctx = ParseeCreateRequest( conf, @@ -60,11 +62,13 @@ ASBan(const ParseeConfig *conf, char *id, char *banned) "@", conf->sender_localpart, ":", conf->server_base ); + id = HttpUrlEncode(id); path = StrConcat(5, "/_matrix/client/v3/rooms/", id, "/ban", "?user_id=", bridge ); Free(bridge); + Free(id); ctx = ParseeCreateRequest( conf, @@ -95,11 +99,13 @@ ASKick(const ParseeConfig *conf, char *id, char *banned) "@", conf->sender_localpart, ":", conf->server_base ); + id = HttpUrlEncode(id); path = StrConcat(5, "/_matrix/client/v3/rooms/", id, "/kick", "?user_id=", bridge ); Free(bridge); + Free(id); ctx = ParseeCreateRequest( conf, @@ -120,7 +126,8 @@ ASJoin(const ParseeConfig *conf, char *id, char *masquerade) { HttpClientContext *ctx = NULL; HashMap *json = NULL; - char *path, *ret; + char *path, *ret, *serv; + int status; if (!conf || !id) { return NULL; @@ -139,6 +146,11 @@ ASJoin(const ParseeConfig *conf, char *id, char *masquerade) { masquerade = HttpUrlEncode(masquerade); } + serv = strchr(id, ':'); + if (serv) + { + serv = serv + 1; + } id = HttpUrlEncode(id); path = StrConcat(5, "/_matrix/client/v3/join/", id, "?", @@ -152,7 +164,7 @@ ASJoin(const ParseeConfig *conf, char *id, char *masquerade) Free(path); json = HashMapCreate(); ASAuthenticateRequest(conf, ctx); - ParseeSetRequestJSON(ctx, json); + status = ParseeSetRequestJSON(ctx, json); JsonFree(json); json = JsonDecode(HttpClientStream(ctx)); @@ -163,6 +175,8 @@ ASJoin(const ParseeConfig *conf, char *id, char *masquerade) Free(masquerade); Free(id); + (void) serv; // TODO + return ret; } void diff --git a/src/Main.c b/src/Main.c index f596126..10c809f 100644 --- a/src/Main.c +++ b/src/Main.c @@ -298,6 +298,7 @@ Main(Array *args, HashMap *env) "7e228734ec8e792960bb5633e43f0cb845f709f61825130490034651136" ); ASSetName(parsee_conf, parsee, "Parsee bridge"); + Free(parsee); } diff --git a/src/MatrixEventHandler.c b/src/MatrixEventHandler.c index 2c5c5bd..32050dd 100644 --- a/src/MatrixEventHandler.c +++ b/src/MatrixEventHandler.c @@ -100,7 +100,7 @@ ParseeMemberHandler(ParseeData *data, HashMap *event) char *jid = ParseeEncodeMXID(state_key); char *sha = NULL, *mime = NULL; char *avatar = ASGetAvatar(data->config, NULL, state_key); - char *url = ParseeToUnauth(data, avatar); + char *url = ParseeToUnauth(data, avatar, NULL); chat_id = ParseeGetFromRoomID(data, room_id); ASGetMIMESHA(data->config, avatar, &mime, &sha); @@ -417,7 +417,7 @@ ParseeMessageHandler(ParseeData *data, HashMap *event) type = direct ? "chat" : "groupchat"; user = GrabString(json, 1, "xmpp_user"); - unauth = ParseeToUnauth(data, url); + unauth = ParseeToUnauth(data, url, GrabString(event, 2, "content", "filename")); encoded_from = ParseeEncodeMXID(m_sender); xmppified_user = StrConcat(3, diff --git a/src/Parsee/User.c b/src/Parsee/User.c index 5a945ea..a9320d8 100644 --- a/src/Parsee/User.c +++ b/src/Parsee/User.c @@ -687,12 +687,13 @@ end: #include char * -ParseeToUnauth(ParseeData *data, char *mxc) +ParseeToUnauth(ParseeData *data, char *mxc, char *filename) { Uri *url = NULL; char *ret; char *key, *hmac; #define PAT "%s/media/%s%s?hmac=%s" +#define PATF "%s/media/%s%s/%s?hmac=%s" size_t l; if (!data || !mxc) { @@ -713,19 +714,43 @@ ParseeToUnauth(ParseeData *data, char *mxc) hmac = ParseeHMACS(data->id, key); Free(key); - l = snprintf(NULL, 0, - PAT, - data->config->media_base, - url->host, url->path, - hmac - ); + if (!filename) + { + l = snprintf(NULL, 0, + PAT, + data->config->media_base, + url->host, url->path, + hmac + ); + } + else + { + l = snprintf(NULL, 0, + PATF, + data->config->media_base, + url->host, url->path, filename, + hmac + ); + } ret = Malloc(l + 3); - snprintf(ret, l + 1, - PAT, - data->config->media_base, - url->host, url->path, - hmac - ); + if (!filename) + { + snprintf(ret, l + 1, + PAT, + data->config->media_base, + url->host, url->path, + hmac + ); + } + else + { + snprintf(ret, l + 1, + PATF, + data->config->media_base, + url->host, url->path, filename, + hmac + ); + } UriFree(url); Free(hmac); return ret; diff --git a/src/Unistr.c b/src/Unistr.c index a1eb1e4..7eab2e0 100644 --- a/src/Unistr.c +++ b/src/Unistr.c @@ -277,3 +277,38 @@ UnistrGetOffset(Unistr *str, uint32_t sep) } return 0; } +size_t +UnistrGetUTFOffset(char *cstr, size_t unicode) +{ + Unistr *tmp; + size_t ret = 0; + if (!cstr) + { + return 0; + } + + tmp = UnistrCreate(cstr); + for (size_t i = 0; i < unicode && i < tmp->length; i++) + { + uint32_t codepoint = tmp->codepoints[i]; + if (codepoint >= 0x0000 && codepoint <= 0x007F) + { + ret += 1; + } + else if (codepoint >= 0x0080 && codepoint <= 0x07FF) + { + ret += 2; + } + else if (codepoint >= 0x0800 && codepoint <= 0xFFFF) + { + ret += 3; + } + else if (codepoint >= 0x010000 && codepoint <= 0x10FFFF) + { + ret += 4; + } + } +end: + Free(tmp); + return ret; +} diff --git a/src/XMPP/Stanza.c b/src/XMPP/Stanza.c index 27a658e..58c3876 100644 --- a/src/XMPP/Stanza.c +++ b/src/XMPP/Stanza.c @@ -159,6 +159,31 @@ XMPPGetReply(XMLElement *elem) return HashMapGet(rep->attrs, "id"); } +ssize_t +XMPPGetReplyOffset(XMLElement *elem) +{ + if (!elem) + { + return -1; + } + for (size_t i = 0; i < ArraySize(elem->children); i++) + { + XMLElement *child = ArrayGet(elem->children, i); + char *xmlns = HashMapGet(child->attrs, "xmlns"); + char *xfor = HashMapGet(child->attrs, "for"); + if (StrEquals(child->name, "fallback") && + StrEquals(xmlns, "urn:xmpp:feature-fallback:0") && + StrEquals(xfor, "urn:xmpp:reply:0")) + { + XMLElement *body = XMLookForUnique(child, "body"); + if (body && HashMapGet(body->attrs, "end")) + { + return strtol(HashMapGet(body->attrs, "end"), NULL, 10); + } + } + } + return -1; +} char * XMPPGetModeration(XMLElement *stanza) { diff --git a/src/XMPPThread/Stanzas/Message.c b/src/XMPPThread/Stanzas/Message.c index 5497f19..c4066d9 100644 --- a/src/XMPPThread/Stanzas/Message.c +++ b/src/XMPPThread/Stanzas/Message.c @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -324,8 +325,9 @@ end_error: { Log(LOG_DEBUG, "Fetching bridge: %fs", Elapsed(rectime)); } + char *trim = ParseeTrimJID(from); if (!mroom_id && !room && !XMPPIsParseeStanza(stanza) && - to && *to == '@') + to && *to == '@' && !XMPPQueryMUC(jabber, trim, NULL)) { DbRef *room_ref; HashMap *room_json; @@ -344,6 +346,7 @@ end_error: ParseePushDMRoom(args, to, from, room); } } + Free(trim); /* TODO: THIS IS A HACK. THIS CODE IGNORES ALL MUC MESSAGES EVER * SENT TO NON-PARSEE PUPPETS, AS A "FIX" TO THE MULTITHREADED @@ -518,6 +521,15 @@ end_error: * too. Go figure. */ size_t off = reply_to ? ParseeFindDatastart(data->data) : 0; + size_t stanzaoff = XMPPGetReplyOffset(stanza); + if (reply_to && stanzaoff != -1) + { + off = UnistrGetUTFOffset(data->data, stanzaoff); + } + if (data->data && off >= strlen(data->data)) + { + off = 0; + } HashMap *ev = MatrixCreateMessage(data->data + off); if (reply_to) { diff --git a/src/include/Parsee.h b/src/include/Parsee.h index 5726286..ea5d18b 100644 --- a/src/include/Parsee.h +++ b/src/include/Parsee.h @@ -368,7 +368,7 @@ extern char * ParseeDMEventFromID(ParseeData *d, char *r_id, char *ori_id); extern char * ParseeDMEventFromSID(ParseeData *d, char *r_id, char *ori_id); /* Gets a Parsee "shim" link to an MXC, usable as unauth for a limited time */ -extern char * ParseeToUnauth(ParseeData *data, char *mxc); +extern char * ParseeToUnauth(ParseeData *data, char *mxc, char *filename); extern void ParseeInitialiseOIDTable(void); extern void ParseePushOIDTable(char *muc, char *occupant); diff --git a/src/include/Routes.h b/src/include/Routes.h index b927eff..664032b 100644 --- a/src/include/Routes.h +++ b/src/include/Routes.h @@ -79,7 +79,8 @@ typedef struct ParseeCmdArg { X_ROUTE("/_matrix/app/v1/users/(.*)", RouteUserAck) \ X_ROUTE("/_matrix/app/v1/rooms/(.*)", RouteRoomAck) \ X_ROUTE("/_matrix/app/v1/ping", RoutePing) \ - X_ROUTE("/media/(.*)/(.*)", RouteMedia) + X_ROUTE("/media/(.*)/(.*)", RouteMedia) \ + X_ROUTE("/media/(.*)/(.*)/(.*)", RouteMedia) #define X_ROUTE(path, name) extern void * name(Array *, void *); ROUTES diff --git a/src/include/Unistring.h b/src/include/Unistring.h index d90d61c..7eff7a1 100644 --- a/src/include/Unistring.h +++ b/src/include/Unistring.h @@ -82,4 +82,10 @@ extern Unistr * UnistrFilter(Unistr *str, UnistrFilterFunc filter); * -------- * Returns: an offset of the first line to not start by {c} | 0 */ extern size_t UnistrGetOffset(Unistr *str, uint32_t sep); + +/** Locates the new index within a regular UTF-8 sequence from an index + * within all codepoints. + * ----------------------------------- + * Returns: an offset */ +extern size_t UnistrGetUTFOffset(char *cstr, size_t unicode); #endif diff --git a/src/include/XMPP.h b/src/include/XMPP.h index 22e98f6..3b53f04 100644 --- a/src/include/XMPP.h +++ b/src/include/XMPP.h @@ -90,6 +90,9 @@ extern char * XMPPGetRetractedID(XMLElement *); /* Get the replied-to stanza ID, if existent. */ extern char * XMPPGetReply(XMLElement *elem); +/* Get the replied-to stanza offset, if existent. */ +extern ssize_t XMPPGetReplyOffset(XMLElement *elem); + /** Get the moderated message ID(as a stanza ID/plain ID) from a moderation * stanza, that lives *alongside* the stanza itself. * ----------------------------------------------------------------------