diff --git a/XEPS-TBD.TXT b/XEPS-TBD.TXT index 11a08d4..712c756 100644 --- a/XEPS-TBD.TXT +++ b/XEPS-TBD.TXT @@ -34,6 +34,8 @@ For future XEPs: - https://xmpp.org/extensions/xep-0050.html Ad-hoc commands that bridge maintainers can deal with XMPP-style are also a nice to have. + - https://xmpp.org/extensions/xep-0425.html + As mentionned in #2, moderation _needs_ to be done. ON STANDBY BECAUSE THESE HAVE BEEN TERRIBLE TO DEAL WITH AND WHO KEEPS WRITING THESE I WANT TO SEND THEM A NICE, BRIGHT GIFT: diff --git a/src/Main.c b/src/Main.c index 0c6e9fe..f4dd4d7 100644 --- a/src/Main.c +++ b/src/Main.c @@ -70,7 +70,6 @@ Main(void) Log(LOG_NOTICE, "Setting up local Matrix user..."); ASRegisterUser(parsee_conf, parsee_conf->sender_localpart); - conf.port = parsee_conf->port; conf.threads = 4; conf.maxConnections = 32; diff --git a/src/Parsee/User.c b/src/Parsee/User.c index 08fd32d..a61c812 100644 --- a/src/Parsee/User.c +++ b/src/Parsee/User.c @@ -177,7 +177,7 @@ ParseeEncodeJID(const ParseeConfig *c, char *jid, bool trim) /* RID: Break everything and die. */ break; } - if (islower(*cs) || isalpha(*cs) || *cs == '_' || + if (islower(*cs) || isalnum(*cs) || *cs == '_' || *cs == '=' || *cs == '-' || *cs == '/' || *cs == '+' || *cs == '.') { @@ -233,7 +233,6 @@ ParseeGetLocal(char *mxid) return cpy; } -/* TODO: More robust system */ char * ParseeEncodeMXID(char *mxid) { @@ -247,6 +246,8 @@ ParseeEncodeMXID(char *mxid) for (i = 0; i < strlen(mxid) + 1; i++) { char src = mxid[i]; + + /* TODO: More robust system */ if (src == '@') { src = '%'; @@ -426,11 +427,8 @@ ParseePushMUC(ParseeData *data, char *room_id, char *jid) } } j = DbJson(ref); - { - - JsonSet(j, JsonValueString(chatid), 2, "mucs", jid); - JsonSet(j, JsonValueString(chatid), 2, "rooms", room_id); - } + JsonSet(j, JsonValueString(chatid), 2, "mucs", jid); + JsonSet(j, JsonValueString(chatid), 2, "rooms", room_id); DbUnlock(data->db, ref); return chatid; diff --git a/src/XMPP/Component.c b/src/XMPP/Component.c index d1ca9cf..e32c921 100644 --- a/src/XMPP/Component.c +++ b/src/XMPP/Component.c @@ -13,19 +13,12 @@ #include -/* TODO: Write the stream system once we have our XML implementation - * checked out. - * - * Did I mention I _hate_ writing XML SAX parsers? Oh, well, they're - * easier than making a DOM directly, so eeh. */ - /* The default component port Prosody uses. */ #define DEFAULT_PROSODY_PORT 5347 XMPPComponent * XMPPInitialiseCompStream(char *host, int port) { - /* TODO */ int sd = -1; struct addrinfo hints, *res, *res0; int error; diff --git a/src/XMPP/Stanza.c b/src/XMPP/Stanza.c index b187b2c..d30a9de 100644 --- a/src/XMPP/Stanza.c +++ b/src/XMPP/Stanza.c @@ -416,3 +416,39 @@ XMPPAnnotatePresence(XMLElement *presence) Free(ver); XMLAddChild(presence, c); } + +char * +XMPPGetModeration(XMLElement *stanza) +{ +#define MOD_BASE "urn:xmpp:message-moderate" + XMLElement *moderate; + XMLElement *fasten; + if (!stanza) + { + return NULL; + } + + /* 0.3.0 version of XEP-0425: Bare look at the moderate element */ + moderate = XMLookForTKV(stanza, "moderate", "xmlns", MOD_BASE ":1"); + if (moderate) + { + Log(LOG_WARNING, "0.3.0 moderation"); + return HashMapGet(moderate->attrs, "id"); + } + + /* Earlier versions, which still depend on fastening. */ + fasten = XMLookForTKV( + stanza, "apply-to", + "xmlns", "urn:xmpp:fasten:0" + ); + moderate = XMLookForTKV( + fasten, "moderated", + "xmlns", MOD_BASE ":0" + ); + if (moderate) + { + return HashMapGet(fasten->attrs, "id"); + } + return NULL; +#undef MOD_BASE +} diff --git a/src/XMPPThread.c b/src/XMPPThread.c index 26f9b20..d55f8a4 100644 --- a/src/XMPPThread.c +++ b/src/XMPPThread.c @@ -26,6 +26,10 @@ AdvertiseSimple("urn:xmpp:avatar:data+notify") \ AdvertiseSimple("urn:xmpp:avatar:metadata") \ AdvertiseSimple("urn:xmpp:message-correct:0") \ + AdvertiseSimple("urn:xmpp:message-moderate:0") \ + AdvertiseSimple("urn:xmpp:message-moderate:1") \ + AdvertiseSimple("urn:xmpp:message-retract:0") \ + AdvertiseSimple("urn:xmpp:message-retract:1") \ AdvertiseSimple("urn:xmpp:avatar:data") \ AdvertiseSimple("urn:xmpp:chat-markers:0") \ AdvertiseSimple("urn:xmpp:reactions:0") \ @@ -54,6 +58,12 @@ ParseeJID(ParseeData *data) { return StrConcat(2, "parsee@", data->config->component_host); } +static char * +ParseeMXID(ParseeData *data) +{ + return StrConcat(4, "@", data->config->sender_localpart, + ":", data->config->homeserver_host); +} static int ICollate(unsigned char *cata, unsigned char *catb) @@ -401,6 +411,10 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr) char *to, *room, *from, *from_matrix, *decode_from; char *mroom_id = NULL; + char *replaced = XMPPGetReplacedID(stanza); + char *retracted = XMPPGetRetractedID(stanza); + char *reply_to = XMPPGetReply(stanza); + char *moderated = XMPPGetModeration(stanza); size_t i; to = NULL; @@ -415,6 +429,30 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr) return false; } + if (moderated) + { + /* TODO: Parsee MUST check if it is a valid MUC */ + char *resource = ParseeGetResource(from); + char *chat_id = ParseeGetFromMUCID(args, from); + char *event_id = NULL; + char *encoded = ParseeMXID(args); + mroom_id = ParseeGetBridgedRoom(args, stanza); + if (!resource && chat_id) + { + event_id = ParseeGetEventFromID(args, stanza, moderated); + ASRedact(args->config, mroom_id, encoded, event_id); + ParseePushAllStanza(args, stanza, event_id); + pthread_mutex_unlock(&thr->info->chk_lock); + + Free(event_id); + } + Free(mroom_id); + Free(resource); + Free(encoded); + Free(chat_id); + } + body = XMLookForUnique(stanza, "body"); + event = XMLookForTKV(stanza, "event", "xmlns", "http://jabber.org/protocol/pubsub#event" ); @@ -497,7 +535,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr) } #undef CHAT_STATES - body = XMLookForUnique(stanza, "body"); if (!body) { XMLFreeElement(stanza); @@ -534,9 +571,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr) char *res = ParseeGetResource(from); char *encoded = ParseeEncodeJID(args->config, decode_from, false); char *event_id = NULL; - char *replaced = XMPPGetReplacedID(stanza); - char *retracted = XMPPGetRetractedID(stanza); - char *reply_to = XMPPGetReply(stanza); bool chat = false; if (StrEquals(HashMapGet(stanza->attrs, "type"), "chat")) @@ -631,6 +665,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr) else if (retracted) { event_id = ParseeGetEventFromID(args, stanza, retracted); + Log(LOG_WARNING, "RETRACTING %s %s", retracted, event_id); ASRedact(args->config, mroom_id, encoded, event_id); ParseePushAllStanza(args, stanza, event_id); pthread_mutex_unlock(&thr->info->chk_lock); @@ -1099,8 +1134,17 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) { HashMap *powers = ASGetPL(args->config, room); int64_t level = GrabInteger(powers, 2, "users", from_matrix); + char *parsee = ParseeMXID(args); - if (powers && level != power_level) + /* I may or may not have fucked up the state hard with this + * lacking any checking. (--gen) */ + if (StrEquals(parsee, from_matrix)) + { + /* TODO: Give the user an achievement, this is goofy. */ + Log(LOG_ERR, "BAD PL DOWNGRADE (%d->%d)", level, power_level); + } + if (powers && level != power_level && + !StrEquals(parsee, from_matrix)) { HashMap *users = GrabObject(powers, 1, "users"); JsonValue *val = JsonValueInteger(power_level); @@ -1113,6 +1157,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza) { JsonFree(powers); } + Free(parsee); } if (StrEquals(type, "unavailable")) diff --git a/src/include/XMPP.h b/src/include/XMPP.h index 064ce26..29fe081 100644 --- a/src/include/XMPP.h +++ b/src/include/XMPP.h @@ -73,7 +73,19 @@ extern char * XMPPGetRetractedID(XMLElement *); /* Get the replied-to stanza ID, if existent. */ extern char * XMPPGetReply(XMLElement *elem); -/* Generate the B64-encoded SHA-256 hash for the 'ver' field in caps. */ +/** Get the moderated message ID(as a stanza ID/plain ID) from a moderation + * stanza, that lives *alongside* the stanza itself. + * ---------------------------------------------------------------------- + * Returns: The stanza ID[LA:stanza] | NULL + * Modifies: NOTHING + * See-Also: https://xmpp.org/extensions/xep-0425.html */ +extern char * XMPPGetModeration(XMLElement *stanza); + +/** Generate the B64-encoded SHA-256 hash for the 'ver' field in caps. + * -------- + * Returns: A base64 encoded ver hash[LA:HEAP] + * Modifies: NOTHING + * See-Also: https://xmpp.org/extensions/xep-0115.html */ extern char * XMPPGenerateVer(void); /* Annotates a presence with https://xmpp.org/extensions/xep-0115.html */