diff --git a/src/MatrixEventHandler.c b/src/MatrixEventHandler.c index 715103b..6500c61 100644 --- a/src/MatrixEventHandler.c +++ b/src/MatrixEventHandler.c @@ -55,6 +55,7 @@ ParseeMemberHandler(ParseeData *data, HashMap *event) { char *muc = ParseeGetMUCID(data, chat_id); char *rev = StrConcat(2, muc, "/parsee"); + /* Make the user join the MUC */ XMPPJoinMUC(data->jabber, jid, rev); Free(rev); @@ -63,9 +64,12 @@ ParseeMemberHandler(ParseeData *data, HashMap *event) Free(jid); Free(chat_id); } - else if (StrEquals(membership, "leave") && !ParseeIsPuppet(conf, state_key)) + else if ((StrEquals(membership, "leave") || + StrEquals(membership, "ban")) + && !ParseeIsPuppet(conf, state_key)) { - /* TODO: Manage bans */ + /* TODO: Manage bans on their own, rather than a spicy leave. + * Then again, this could cause desync issues. */ XMPPComponent *jabber = data->jabber; char *jid = ParseeEncodeMXID(state_key); char *name = NULL, *rev = NULL, *muc_id = NULL; @@ -84,7 +88,6 @@ ParseeMemberHandler(ParseeData *data, HashMap *event) rev = StrConcat(4, muc_id, "/", name, "[p]"); XMPPLeaveMUC(jabber, jid, rev, reason); - end: Free(chat_id); Free(muc_id); @@ -104,7 +107,11 @@ ParseeBotHandler(ParseeData *data, HashMap *event) "@", data->config->sender_localpart, ":", data->config->homeserver_host ); - Command *cmd; + Command *cmd = NULL; + ParseeCmdArg arg = { + .data = data, + .event = event + }; if (StrEquals(msgtype, "m.notice")) { @@ -137,13 +144,7 @@ ParseeBotHandler(ParseeData *data, HashMap *event) body++; cmd = CommandParse(body); - { - ParseeCmdArg arg; - arg.data = data; - arg.event = event; - - RouteCommand(data->handler, cmd, &arg); - } + RouteCommand(data->handler, cmd, &arg); Free(profile); CommandFree(cmd); @@ -308,10 +309,16 @@ ParseeEventHandler(ParseeData *data, HashMap *event) ParseeMemberHandler(data, event); return; } - if (StrEquals(event_type, "m.room.message")) + else if (StrEquals(event_type, "m.room.message")) { ParseeMessageHandler(data, event); return; } + else if (StrEquals(event_type, "m.room.redaction")) + { + Log(LOG_WARNING, "Unsupported event redaction %s", event_id); + /* TODO: Implement Matrix->XMPP redactions. */ + } + } diff --git a/src/XMPPThread.c b/src/XMPPThread.c index 410ea38..5c30248 100644 --- a/src/XMPPThread.c +++ b/src/XMPPThread.c @@ -48,6 +48,12 @@ typedef struct XMPPIdentity { char *category, *type, *lang, *name; } XMPPIdentity; +static char * +ParseeJID(ParseeData *data) +{ + return StrConcat(2, "parsee@", data->config->component_host); +} + static int ICollate(unsigned char *cata, unsigned char *catb) { @@ -306,8 +312,6 @@ CreateAvatarRequest(char *from, char *to, char *avatar_id) XMLAddAttr(items, "node", "urn:xmpp:avatar:data"); XMLAddChild(pubsub, items); - - item = XMLCreateTag("item"); XMLAddAttr(item, "id", avatar_id); XMLAddChild(items, item); @@ -335,8 +339,6 @@ CreatePubsubRequest(char *from, char *to, char *node) XMLAddAttr(sub, "jid", from); XMLAddChild(pubsub, sub); - //Log(LOG_INFO, "Subscribed to %s's %s node", to, node); - Free(id); return iq_req; } @@ -406,6 +408,11 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr) from_matrix = NULL; from = HashMapGet(stanza->attrs, "from"); + if (ParseeManageBan(args, from, NULL)) + { + XMLFreeElement(stanza); + return false; + } event = XMLookForTKV(stanza, "event", "xmlns", "http://jabber.org/protocol/pubsub#event" @@ -539,7 +546,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr) } { - char *parsee = StrConcat(2, "parsee@", args->config->component_host); + char *parsee = ParseeJID(args); XMLElement *ps = CreatePubsubRequest( parsee, decode_from, "urn:xmpp:avatar:metadata" @@ -839,9 +846,11 @@ IQResult(ParseeData *args, XMLElement *stanza) b64len = base64 ? strlen(base64) : 0; length = Base64DecodedSize(base64, b64len); - /* TODO: Bound checks for a size limit. */ + /* TODO: Bound checks for a size limit. */ bdata = (char *) Base64Decode(base64, b64len); datastream = StrStreamReaderN(bdata, length); + + /* XEP-0084 effectively assumes an image/png MIME. */ mxc = ASUpload(args->config, datastream, length, "image/png"); jid = ParseeLookupJID(from); @@ -850,8 +859,8 @@ IQResult(ParseeData *args, XMLElement *stanza) JsonValueFree(JsonSet( json, JsonValueString(id), - 1, from) - ); + 1, from + )); DbUnlock(args->db, avatars); Free(mxc); @@ -1053,7 +1062,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) #define IsStatus(code) (status && \ StrEquals(HashMapGet(status->attrs, "code"), #code)) char *jid = item ? HashMapGet(item->attrs, "jid") : NULL; - char *from; + char *from = NULL; char *type = HashMapGet(stanza->attrs, "type"); char *room = ParseeGetBridgedRoom(args, stanza); char *decode_from = ParseeLookupJID(oid); @@ -1066,14 +1075,13 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) Free(from_matrix); from_matrix = ParseeEncodeJID(args->config, decode_from, false); } - /* TODO: Use affiliation to set PL */ if (StrEquals(affiliation, "owner")) { power_level = 98; } else if (StrEquals(affiliation, "admin")) { - power_level = 51; + power_level = 50; } else if (StrEquals(affiliation, "member")) { @@ -1107,11 +1115,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) if (StrEquals(type, "unavailable")) { - /* TODO: Treat as a ban if the role is outcast. - * Modify the code to be more accurate later. */ - /* If not an MXID, use the Parsee user */ - if (IsStatus(301)) { ASBan(args->config, room, from_matrix); @@ -1122,8 +1126,8 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) } else if (IsStatus(303)) { - /* TODO: This is a nick change. */ - Log(LOG_WARNING, "Nick change not implemented."); + char *nick = HashMapGet(item->attrs, "nick"); + ASSetName(args->config, from_matrix, nick); } else { @@ -1136,7 +1140,6 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) { ParseePushJIDTable(oid, jid); } - from = StrConcat(2, "parsee@", args->config->component_host); Free(from); Free(decode_from); @@ -1180,7 +1183,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) DbUnlock(args->db, avatars); - from = StrConcat(2, "parsee@", args->config->component_host); + from = ParseeJID(args); vcard_request = CreateVCardRequest( from, HashMapGet(stanza->attrs, "from") @@ -1198,7 +1201,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) if (0) { XMPPComponent *jabber = args->jabber; - char *from = StrConcat(2, "parsee@", args->config->component_host); + char *from = ParseeJID(args); XMLElement *vcard_request = CreateVCardRequest( from, HashMapGet(stanza->attrs, "from") @@ -1380,40 +1383,40 @@ ParseeXMPPThread(void *argp) XMLElement * ParseeAwaitStanza(char *identifier) { - XMPPAwait awa, *await; + /* TODO: Pthreads HATE me using Malloc here, so I'm abusing stackspace. + * Not *too much* of a problem, just a weird oddity. If anyone has a clue + * on why that happens (at least on ARM64 with a Pi4 running Debian), let + * me know! */ + XMPPAwait awa; XMLElement *stanza; if (!identifier) { return NULL; } - /* TODO: Pthreads HATE me using Malloc here, so I'm abusing stackspace. - * Not *too much* of a problem, just a weird oddity. If anyone has a clue - * on why that happens (at least on ARM64 with a Pi4 running Debian), let - * me know! */ - await = &awa; pthread_mutex_lock(&await_lock); - pthread_cond_init(&await->condition, NULL); - pthread_mutex_init(&await->cond_lock, NULL); - await->stanza = NULL; + pthread_cond_init(&awa.condition, NULL); + pthread_mutex_init(&awa.cond_lock, NULL); + awa.stanza = NULL; - HashMapSet(await_table, identifier, await); + HashMapSet(await_table, identifier, &awa); pthread_mutex_unlock(&await_lock); - pthread_mutex_lock(&await->cond_lock); - while (!await->stanza) + pthread_mutex_lock(&awa.cond_lock); + while (!awa.stanza) { - pthread_cond_wait(&await->condition, &await->cond_lock); + /* TODO: Allow timeouts. */ + pthread_cond_wait(&awa.condition, &awa.cond_lock); } - stanza = await->stanza; + stanza = awa.stanza; pthread_mutex_lock(&await_lock); pthread_mutex_unlock(&await_lock); - pthread_mutex_unlock(&await->cond_lock); + pthread_mutex_unlock(&awa.cond_lock); - pthread_cond_destroy(&await->condition); - pthread_mutex_destroy(&await->cond_lock); + pthread_cond_destroy(&awa.condition); + pthread_mutex_destroy(&awa.cond_lock); return stanza; }