#include "XMPPThread/internal.h" #include #include #include #include #include #include char * ParseeGetBridgedRoom(ParseeData *data, XMLElement *stanza) { char *to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to")); char *from = HashMapGet(stanza->attrs, "from"); char *chat_id = ParseeGetFromMUCID(data, from); char *mroom_id = ParseeGetRoomID(data, chat_id); char *ret; Free(chat_id); if (mroom_id) { Free(to); return mroom_id; } /* Not a MUC, find the DMd room. */ ret = ParseeFindDMRoom(data, to, from); Free(to); return ret; } char * ParseeGetEventFromID(ParseeData *data, XMLElement *stanza, char *id) { char *from = (HashMapGet(stanza->attrs, "from")); char *chat_id = ParseeGetFromMUCID(data, from); char *ret = ParseeEventFromSID(data, chat_id, id); char *mroom_id = ParseeGetBridgedRoom(data, stanza); if (!ret) { Free(ret); ret = ParseeEventFromID(data, chat_id, id); } Free(chat_id); if (ret) { Free(mroom_id); return ret; } ret = ParseeDMEventFromID(data, mroom_id, id); Free(mroom_id); return ret; } char * ParseeGetReactedEvent(ParseeData *data, XMLElement *stanza) { XMLElement *reactions = XMLookForTKV(stanza, "reactions", "xmlns", "urn:xmpp:reactions:0" ); char *reacted_id = reactions ? HashMapGet(reactions->attrs, "id") : NULL; return ParseeGetEventFromID(data, stanza, reacted_id); } void ParseePushAllStanza(ParseeData *args, XMLElement *stanza, char *event) { char *xmpp_from = HashMapGet(stanza->attrs, "from"); char *mroom_id = ParseeGetBridgedRoom(args, stanza); char *chat_id = ParseeGetFromMUCID(args, xmpp_from); char *id_str = HashMapGet(stanza->attrs, "id"); char *s_id_str = XMPPGetStanzaID(stanza); if (!chat_id) { ParseePushDMStanza( args, mroom_id, s_id_str, id_str, event, xmpp_from ); } ParseePushStanza(args, chat_id, s_id_str, id_str, event, xmpp_from); Free(mroom_id); Free(chat_id); } bool ParseeVerifyAllStanza(ParseeData *args, XMLElement *stanza) { char *to, *room; char *from = HashMapGet(stanza->attrs, "from"); char *id = HashMapGet(stanza->attrs, "id"); char *chat_id = ParseeGetFromMUCID(args, from); bool ret; if (chat_id) { char *s_id_str = XMPPGetStanzaID(stanza); ret = ParseeVerifyStanza(args, chat_id, s_id_str); Free(chat_id); return ret; } to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to")); room = ParseeFindDMRoom(args, to, from); ret = ParseeVerifyDMStanza(args, chat_id, id); Free(room); Free(to); return ret; } /* TODO: Cache this information. */ bool ServerHasXEP421(ParseeData *data, char *from) { char *server = NULL, *parsee; XMLElement *disco; bool ret; if (!data || !from) { return false; } server = strchr(from, '@'); if (!server) { server = from; } else { server++; } server = StrDuplicate(server); if (strchr(server, '/')) { *(strchr(server, '/')) = '\0'; } parsee = ParseeJID(data); disco = XMPPSendDisco(data->jabber, parsee, server); ret = XMPPDiscoAdvertises(disco, "urn:xmpp:occupant-id:0"); XMLFreeElement(disco); Free(parsee); Free(server); return ret; } /* Scrambles an Occupant ID so that Matrix can use it for MXIDs. * Occupant IDs are to be treated as opaque, therefore, we hash them * into a SHA-256 value * > "The recipient MUST consider the occupant identifier to be an opaque * > string.". */ static char * ScrambleOID(ParseeData *data, char *opaque_oid) { unsigned char *raw; char *sha, *mxid; const ParseeConfig *c = data->config; if (!opaque_oid) { return NULL; } /* Turns this into a 128-byte long, Matrix-safe value. */ raw = Sha256(opaque_oid); sha = ShaToHex(raw); Free(raw); /* TODO: Either mark this specially, or drop Parsee JID flags * altogether before any 1.0.0 */ mxid = StrConcat( 6, "@", c->namespace_base, "_l_", sha, ":", c->server_base ); Free(sha); return mxid; } /* TODO: Shove that function everywhere one can see fit. */ char * ParseeGetBridgedUserI(ParseeData *data, XMLElement *stanza, char *force) { char *user, *xmpp_from, *type; char *decode_from, *occ_id = NULL, *looked = NULL; bool is_chat, has_anon = false, is_anon = false; if (!data || !stanza) { return NULL; } xmpp_from = force ? force : HashMapGet(stanza->attrs, "from"); type = HashMapGet(stanza->attrs, "type"); decode_from = ParseeLookupJID(xmpp_from); is_chat = StrEquals(type, "chat"); if (!is_chat) { has_anon = ServerHasXEP421(data, xmpp_from); is_anon = has_anon && StrEquals(xmpp_from, decode_from); } if (is_anon || force) { XMLElement *occupant; occupant = XMLookForTKV( stanza, "occupant-id", "xmlns", "urn:xmpp:occupant-id:0" ); occ_id = occupant ? HashMapGet(occupant->attrs, "id") : NULL; if (!occ_id) { occ_id = ParseeLookupOID(xmpp_from); looked = occ_id; } else { ParseePushOIDTable(xmpp_from, occ_id); } } if (!occ_id) { user = ParseeEncodeJID( data->config, decode_from, type ? is_chat : false ); Free(decode_from); Free(looked); return user; } Free(decode_from); Free(looked); return ScrambleOID(data, occ_id); }