mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 18:35:11 +00:00
[ADD/WIP] Start unifying DMs and MUCs
I really need to dispatch XMPP stanza management.
This commit is contained in:
parent
6b0f08c49e
commit
5f2c3a9cb8
10 changed files with 570 additions and 87 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <AS.h>
|
#include <AS.h>
|
||||||
|
|
||||||
|
#include <Cytoplasm/Log.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
CommandHead(CmdSetPL, cmd, argp)
|
CommandHead(CmdSetPL, cmd, argp)
|
||||||
|
|
@ -26,3 +27,25 @@ CommandHead(CmdSetPL, cmd, argp)
|
||||||
));
|
));
|
||||||
ASSetPL(data->config, room, map);
|
ASSetPL(data->config, room, map);
|
||||||
}
|
}
|
||||||
|
CommandHead(CmdSetMin, cmd, argp)
|
||||||
|
{
|
||||||
|
ParseeCmdArg *args = argp;
|
||||||
|
ParseeData *data = args->data;
|
||||||
|
char *event = HashMapGet(cmd->arguments, "event");
|
||||||
|
char *room = HashMapGet(cmd->arguments, "room");
|
||||||
|
char *pl_str = HashMapGet(cmd->arguments, "pl");
|
||||||
|
long pl = strtol(pl_str, NULL, 10);
|
||||||
|
HashMap *map;
|
||||||
|
|
||||||
|
|
||||||
|
if (!event || !pl_str)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map = ASGetPL(data->config, room);
|
||||||
|
JsonValueFree(JsonSet(
|
||||||
|
map, JsonValueInteger(pl),
|
||||||
|
2, "events", event
|
||||||
|
));
|
||||||
|
ASSetPL(data->config, room, map);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ ParseeMemberHandler(ParseeData *data, HashMap *event)
|
||||||
|
|
||||||
if (StrEquals(membership, "invite") && ParseeIsPuppet(conf, state_key))
|
if (StrEquals(membership, "invite") && ParseeIsPuppet(conf, state_key))
|
||||||
{
|
{
|
||||||
DbRef *ref;
|
DbRef *ref = NULL;
|
||||||
HashMap *json;
|
HashMap *json;
|
||||||
char *jid;
|
char *jid;
|
||||||
bool direct = GrabBoolean(event, 2, "content", "is_direct");
|
bool direct = GrabBoolean(event, 2, "content", "is_direct");
|
||||||
|
|
@ -125,18 +125,24 @@ static void
|
||||||
ParseeMessageHandler(ParseeData *data, HashMap *event)
|
ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
{
|
{
|
||||||
XMPPComponent *jabber = data->jabber;
|
XMPPComponent *jabber = data->jabber;
|
||||||
DbRef *ref;
|
DbRef *ref = NULL;
|
||||||
HashMap *json;
|
HashMap *json;
|
||||||
|
|
||||||
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
char *msgtype = GrabString(event, 2, "content", "msgtype");
|
||||||
char *body = GrabString(event, 2, "content", "body");
|
char *body = GrabString(event, 2, "content", "body");
|
||||||
char *id = GrabString(event, 1, "room_id");
|
char *id = GrabString(event, 1, "room_id");
|
||||||
char *ev_id = GrabString(event, 1, "event_id");
|
char *ev_id = GrabString(event, 1, "event_id");
|
||||||
char *sender = GrabString(event, 1, "sender");
|
char *m_sender = GrabString(event, 1, "sender");
|
||||||
char *chat_id, *muc_id, *jid;
|
char *chat_id, *muc_id, *jid;
|
||||||
char *reply_id = MatrixGetReply(event);
|
char *reply_id = MatrixGetReply(event);
|
||||||
char *xepd = ParseeXMPPify(event);
|
char *xepd = ParseeXMPPify(event);
|
||||||
char *cmd_lp = data->config->sender_localpart;
|
char *cmd_lp = data->config->sender_localpart;
|
||||||
|
char *type, *user, *xmppified_user = NULL, *to;
|
||||||
|
char *unauth = NULL;
|
||||||
|
char *origin_id = NULL, *stanza = NULL;
|
||||||
|
char *sender = NULL;
|
||||||
|
char *unedited_id = MatrixGetEdit(event);
|
||||||
|
char *url = GrabString(event, 2, "content", "url");
|
||||||
|
|
||||||
bool direct = false;
|
bool direct = false;
|
||||||
|
|
||||||
|
|
@ -146,13 +152,14 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
json = DbJson(ref);
|
json = DbJson(ref);
|
||||||
direct = JsonValueAsBoolean(HashMapGet(json, "is_direct"));
|
direct = JsonValueAsBoolean(HashMapGet(json, "is_direct"));
|
||||||
|
|
||||||
if (ParseeIsPuppet(data->config, sender) ||
|
if (ParseeIsPuppet(data->config, m_sender) ||
|
||||||
ParseeManageBan(data, sender, id))
|
ParseeManageBan(data, m_sender, id))
|
||||||
{
|
{
|
||||||
DbUnlock(data->db, ref);
|
DbUnlock(data->db, ref);
|
||||||
Free(chat_id);
|
Free(chat_id);
|
||||||
Free(reply_id);
|
Free(reply_id);
|
||||||
Free(xepd);
|
Free(xepd);
|
||||||
|
Free(unedited_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,74 +171,99 @@ ParseeMessageHandler(ParseeData *data, HashMap *event)
|
||||||
Free(chat_id);
|
Free(chat_id);
|
||||||
Free(reply_id);
|
Free(reply_id);
|
||||||
Free(xepd);
|
Free(xepd);
|
||||||
|
Free(unedited_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: Reunite DM/MUC code to bring feature parity. */
|
||||||
|
type = direct ? "chat" : "groupchat";
|
||||||
|
user = GrabString(json, 1, "xmpp_user");
|
||||||
|
unauth = ParseeToUnauth(data, url);
|
||||||
if (direct)
|
if (direct)
|
||||||
{
|
{
|
||||||
char *user = GrabString(json, 1, "xmpp_user");
|
xmppified_user = ParseeEncodeMXID(m_sender);
|
||||||
char *local = ParseeEncodeMXID(sender);
|
to = StrDuplicate(user);
|
||||||
|
|
||||||
Log(LOG_INFO," Sending to %s as %s", user, local);
|
|
||||||
|
|
||||||
XMPPSendPlain(jabber, local, user, body, "chat", NULL, NULL, ev_id, NULL, NULL);
|
|
||||||
|
|
||||||
DbUnlock(data->db, ref);
|
|
||||||
Free(chat_id);
|
Free(chat_id);
|
||||||
Free(local);
|
|
||||||
Free(reply_id);
|
|
||||||
Free(xepd);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
DbUnlock(data->db, ref);
|
{
|
||||||
|
char *name, *rev, *stanza;
|
||||||
/* Try to find the chat ID */
|
/* Try to find the chat ID */
|
||||||
muc_id = ParseeGetMUCID(data, chat_id);
|
muc_id = ParseeGetMUCID(data, chat_id);
|
||||||
if (!chat_id)
|
if (!chat_id)
|
||||||
{
|
{
|
||||||
Free(reply_id);
|
goto end;
|
||||||
Free(xepd);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
jid = ParseeEncodeMXID(sender);
|
xmppified_user = ParseeEncodeMXID(m_sender);
|
||||||
{
|
|
||||||
/* TODO: Check the name's validity */
|
|
||||||
char *name = ASGetName(data->config, id, sender);
|
|
||||||
char *rev = StrConcat(4, muc_id, "/", name, "[p]");
|
|
||||||
char *stanza = NULL, *sender = NULL;
|
|
||||||
char *url = GrabString(event, 2, "content", "url");
|
|
||||||
char *unauth = ParseeToUnauth(data, url);
|
|
||||||
|
|
||||||
char *unedited_id = MatrixGetEdit(event);
|
/* TODO: Check the name's validity */
|
||||||
char *origin_id = NULL;
|
name = ASGetName(data->config, id, m_sender);
|
||||||
|
rev = StrConcat(4, muc_id, "/", name, "[p]");
|
||||||
|
|
||||||
|
XMPPJoinMUC(jabber, xmppified_user, rev);
|
||||||
|
|
||||||
|
to = muc_id;
|
||||||
|
|
||||||
|
Free(name);
|
||||||
|
Free(rev);
|
||||||
|
}
|
||||||
if (reply_id)
|
if (reply_id)
|
||||||
{
|
{
|
||||||
ParseeGetStanzaInfo(data, chat_id, reply_id, &stanza, &sender);
|
/* TODO: Monocles chat DM users HATE this trick!
|
||||||
|
* Replies don't work there. Go figure why. */
|
||||||
|
if (!ParseeGetStanzaInfo(data, chat_id, reply_id, &stanza, &sender))
|
||||||
|
{
|
||||||
|
ParseeGetDMStanzaInfo(data, id, reply_id, &stanza, &sender);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (unedited_id)
|
else if (unedited_id)
|
||||||
{
|
{
|
||||||
ParseeGetOrigin(data, chat_id, unedited_id, &origin_id);
|
if (!ParseeGetOrigin(data, chat_id, unedited_id, &origin_id))
|
||||||
|
{
|
||||||
|
ParseeGetDMOrigin(data, id, unedited_id, &origin_id);
|
||||||
}
|
}
|
||||||
XMPPJoinMUC(jabber, jid, rev);
|
}
|
||||||
XMPPSendPlain(
|
|
||||||
jabber, jid, muc_id,
|
if (direct && sender)
|
||||||
xepd ? xepd : body, "groupchat",
|
{
|
||||||
stanza, sender, ev_id, unauth, origin_id
|
char *sndr_tmp = sender;
|
||||||
|
sender = ParseeTrimJID(sender);
|
||||||
|
Free(sndr_tmp);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
char *xmpp_ident = StrRandom(32);
|
||||||
|
XMPPSendPlainID(
|
||||||
|
jabber, xmppified_user, to,
|
||||||
|
xepd ? xepd : body, type,
|
||||||
|
stanza, sender, ev_id, unauth, origin_id,
|
||||||
|
xmpp_ident
|
||||||
);
|
);
|
||||||
Free(rev);
|
/* Culprit */
|
||||||
Free(name);
|
if (direct)
|
||||||
|
{
|
||||||
|
ParseePushDMStanza(
|
||||||
|
data, id, NULL,
|
||||||
|
xmpp_ident, ev_id,
|
||||||
|
xmppified_user
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Free(xmpp_ident);
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
Free(origin_id);
|
||||||
|
Free(xmppified_user);
|
||||||
|
Free(chat_id);
|
||||||
|
Free(to);
|
||||||
|
Free(reply_id);
|
||||||
|
Free(xepd);
|
||||||
Free(stanza);
|
Free(stanza);
|
||||||
Free(sender);
|
Free(sender);
|
||||||
Free(unauth);
|
Free(unauth);
|
||||||
Free(origin_id);
|
|
||||||
Free(unedited_id);
|
Free(unedited_id);
|
||||||
}
|
|
||||||
Free(chat_id);
|
DbUnlock(data->db, ref);
|
||||||
Free(muc_id);
|
|
||||||
Free(jid);
|
|
||||||
Free(reply_id);
|
|
||||||
Free(xepd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -81,8 +81,9 @@ ParseeCleanup(void *datp)
|
||||||
ref = DbLock(data->db, 2, "chats", chat);
|
ref = DbLock(data->db, 2, "chats", chat);
|
||||||
json = DbJson(ref);
|
json = DbJson(ref);
|
||||||
|
|
||||||
#define CleanupField(field, timeout) do \
|
#define CleanupField(field, timeout, threshold) do \
|
||||||
{ \
|
{ \
|
||||||
|
size_t fields = 0, cleaned = 0; \
|
||||||
field##s = JsonValueAsObject(HashMapGet(json, #field"s")); \
|
field##s = JsonValueAsObject(HashMapGet(json, #field"s")); \
|
||||||
to_delete = ArrayCreate(); \
|
to_delete = ArrayCreate(); \
|
||||||
while (HashMapIterate(field##s, &field, (void **) &val)) \
|
while (HashMapIterate(field##s, &field, (void **) &val)) \
|
||||||
|
|
@ -90,31 +91,90 @@ ParseeCleanup(void *datp)
|
||||||
HashMap *obj = JsonValueAsObject(val); \
|
HashMap *obj = JsonValueAsObject(val); \
|
||||||
uint64_t age = JsonValueAsInteger(HashMapGet(obj, "age")); \
|
uint64_t age = JsonValueAsInteger(HashMapGet(obj, "age")); \
|
||||||
uint64_t dur = ts - age; \
|
uint64_t dur = ts - age; \
|
||||||
|
fields++; \
|
||||||
\
|
\
|
||||||
if ((dur > (timeout))) \
|
if ((dur > (timeout))) \
|
||||||
{ \
|
{ \
|
||||||
ArrayAdd(to_delete, StrDuplicate(field)); \
|
ArrayAdd(to_delete, StrDuplicate(field)); \
|
||||||
|
cleaned++; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
for (j = 0; j < ArraySize(to_delete); j++) \
|
for (j = 0; j < ArraySize(to_delete); j++) \
|
||||||
{ \
|
{ \
|
||||||
field = ArrayGet(to_delete, j); \
|
field = ArrayGet(to_delete, j); \
|
||||||
|
if (cleaned > threshold) \
|
||||||
|
{ \
|
||||||
JsonValueFree(HashMapDelete(field##s, field)); \
|
JsonValueFree(HashMapDelete(field##s, field)); \
|
||||||
|
} \
|
||||||
Free(field); \
|
Free(field); \
|
||||||
} \
|
} \
|
||||||
ArrayFree(to_delete); \
|
ArrayFree(to_delete); \
|
||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
CleanupField(stanza, 3 HOURS);
|
CleanupField(stanza, 30 MINUTES, 50);
|
||||||
CleanupField(event, 3 HOURS);
|
CleanupField(event, 30 MINUTES, 50);
|
||||||
CleanupField(id, 3 HOURS);
|
CleanupField(id, 30 MINUTES, 50);
|
||||||
|
|
||||||
DbUnlock(data->db, ref);
|
DbUnlock(data->db, ref);
|
||||||
}
|
}
|
||||||
DbListFree(chats);
|
DbListFree(chats);
|
||||||
/* TODO */
|
/* TODO */
|
||||||
|
chats = DbList(data->db, 1, "rooms");
|
||||||
|
|
||||||
|
for (i = 0; i < ArraySize(chats); i++)
|
||||||
|
{
|
||||||
|
DbRef *ref;
|
||||||
|
HashMap *json, *stanzas, *events, *ids;
|
||||||
|
char *stanza, *event, *id;
|
||||||
|
JsonValue *val;
|
||||||
|
Array *to_delete;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
|
chat = ArrayGet(chats, i);
|
||||||
|
ref = DbLock(data->db, 3, "rooms", chat, "data");
|
||||||
|
json = DbJson(ref);
|
||||||
|
|
||||||
|
#define CleanupField(field, timeout, threshold) do \
|
||||||
|
{ \
|
||||||
|
size_t fields = 0, cleaned = 0; \
|
||||||
|
field##s = JsonValueAsObject(HashMapGet(json, #field"s")); \
|
||||||
|
to_delete = ArrayCreate(); \
|
||||||
|
while (HashMapIterate(field##s, &field, (void **) &val)) \
|
||||||
|
{ \
|
||||||
|
HashMap *obj = JsonValueAsObject(val); \
|
||||||
|
uint64_t age = JsonValueAsInteger(HashMapGet(obj, "age")); \
|
||||||
|
uint64_t dur = ts - age; \
|
||||||
|
fields++; \
|
||||||
|
\
|
||||||
|
if ((dur > (timeout))) \
|
||||||
|
{ \
|
||||||
|
ArrayAdd(to_delete, StrDuplicate(field)); \
|
||||||
|
cleaned++; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
for (j = 0; j < ArraySize(to_delete); j++) \
|
||||||
|
{ \
|
||||||
|
field = ArrayGet(to_delete, j); \
|
||||||
|
if (cleaned > threshold) \
|
||||||
|
{ \
|
||||||
|
JsonValueFree(HashMapDelete(field##s, field)); \
|
||||||
|
} \
|
||||||
|
Free(field); \
|
||||||
|
} \
|
||||||
|
ArrayFree(to_delete); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
CleanupField(stanza, 3 HOURS, 50);
|
||||||
|
CleanupField(event, 3 HOURS, 50);
|
||||||
|
CleanupField(id, 3 HOURS, 50);
|
||||||
|
|
||||||
|
DbUnlock(data->db, ref);
|
||||||
|
}
|
||||||
|
DbListFree(chats);
|
||||||
}
|
}
|
||||||
int
|
int
|
||||||
ParseeFindDatastart(char *data)
|
ParseeFindDatastart(char *data)
|
||||||
|
|
@ -353,6 +413,85 @@ ParseeXMPPify(HashMap *event)
|
||||||
return xepd;
|
return xepd;
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
|
ParseePushDMStanza(ParseeData *data, char *room_id, char *stanza_id, char *id, char *ev, char *sender)
|
||||||
|
{
|
||||||
|
DbRef *ref;
|
||||||
|
HashMap *j;
|
||||||
|
HashMap *stanzas, *obj, *events, *ids;
|
||||||
|
bool new_stanzas = false, new_events = false;
|
||||||
|
bool new_ids = false;
|
||||||
|
uint64_t age = UtilTsMillis();
|
||||||
|
if (!data || !room_id || !ev || !sender)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref = DbLock(data->db, 3, "rooms", room_id, "data");
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
j = DbJson(ref);
|
||||||
|
|
||||||
|
stanzas = JsonValueAsObject(HashMapGet(j, "stanzas"));
|
||||||
|
if (!stanzas)
|
||||||
|
{
|
||||||
|
stanzas = HashMapCreate();
|
||||||
|
new_stanzas = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stanza_id)
|
||||||
|
{
|
||||||
|
obj = HashMapCreate();
|
||||||
|
HashMapSet(obj, "age", JsonValueInteger(age));
|
||||||
|
HashMapSet(obj, "event", JsonValueString(ev));
|
||||||
|
JsonValueFree(HashMapSet(stanzas, stanza_id, JsonValueObject(obj)));
|
||||||
|
|
||||||
|
if (new_stanzas)
|
||||||
|
{
|
||||||
|
HashMapSet(j, "stanzas", JsonValueObject(stanzas));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
events = JsonValueAsObject(HashMapGet(j, "events"));
|
||||||
|
if (!events)
|
||||||
|
{
|
||||||
|
events = HashMapCreate();
|
||||||
|
new_events = true;
|
||||||
|
}
|
||||||
|
obj = HashMapCreate();
|
||||||
|
HashMapSet(obj, "stanza", JsonValueString(stanza_id));
|
||||||
|
HashMapSet(obj, "origin", JsonValueString(id));
|
||||||
|
HashMapSet(obj, "sender", JsonValueString(sender));
|
||||||
|
HashMapSet(obj, "age", JsonValueInteger(age));
|
||||||
|
JsonValueFree(HashMapSet(events, ev, JsonValueObject(obj)));
|
||||||
|
if (new_events)
|
||||||
|
{
|
||||||
|
HashMapSet(j, "events", JsonValueObject(events));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id)
|
||||||
|
{
|
||||||
|
ids = JsonValueAsObject(HashMapGet(j, "ids"));
|
||||||
|
if (!ids)
|
||||||
|
{
|
||||||
|
ids = HashMapCreate();
|
||||||
|
new_ids = true;
|
||||||
|
}
|
||||||
|
obj = HashMapCreate();
|
||||||
|
HashMapSet(obj, "stanza", JsonValueString(stanza_id));
|
||||||
|
HashMapSet(obj, "event", JsonValueString(ev));
|
||||||
|
HashMapSet(obj, "sender", JsonValueString(sender));
|
||||||
|
HashMapSet(obj, "age", JsonValueInteger(age));
|
||||||
|
JsonValueFree(HashMapSet(ids, id, JsonValueObject(obj)));
|
||||||
|
if (new_ids)
|
||||||
|
{
|
||||||
|
HashMapSet(j, "ids", JsonValueObject(ids));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DbUnlock(data->db, ref);
|
||||||
|
}
|
||||||
|
void
|
||||||
ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id, char *id, char *ev, char *sender)
|
ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id, char *id, char *ev, char *sender)
|
||||||
{
|
{
|
||||||
DbRef *ref;
|
DbRef *ref;
|
||||||
|
|
@ -429,6 +568,36 @@ ParseePushStanza(ParseeData *data, char *chat_id, char *stanza_id, char *id, cha
|
||||||
DbUnlock(data->db, ref);
|
DbUnlock(data->db, ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ParseeVerifyDMStanza(ParseeData *data, char *room_id, char *id)
|
||||||
|
{
|
||||||
|
DbRef *ref = NULL;
|
||||||
|
HashMap *j = NULL;
|
||||||
|
HashMap *stanzas = NULL;
|
||||||
|
bool ret = true;
|
||||||
|
if (!data || !room_id || !id)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref = DbLock(data->db, 3, "rooms", room_id, "data");
|
||||||
|
j = DbJson(ref);
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
stanzas = JsonValueAsObject(HashMapGet(j, "ids"));
|
||||||
|
if (!stanzas)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = !HashMapGet(stanzas, id);
|
||||||
|
end:
|
||||||
|
DbUnlock(data->db, ref);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
bool
|
bool
|
||||||
ParseeVerifyStanza(ParseeData *data, char *chat_id, char *stanza_id)
|
ParseeVerifyStanza(ParseeData *data, char *chat_id, char *stanza_id)
|
||||||
{
|
{
|
||||||
|
|
@ -490,6 +659,38 @@ end:
|
||||||
DbUnlock(data->db, ref);
|
DbUnlock(data->db, ref);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
char *
|
||||||
|
ParseeDMEventFromID(ParseeData *data, char *room_id, char *id)
|
||||||
|
{
|
||||||
|
DbRef *ref = NULL;
|
||||||
|
HashMap *j = NULL;
|
||||||
|
HashMap *ids = NULL;
|
||||||
|
char *ret = NULL;
|
||||||
|
if (!data || !room_id || !id)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref = DbLock(data->db, 3, "rooms", room_id, "data");
|
||||||
|
j = DbJson(ref);
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ids = JsonValueAsObject(HashMapGet(j, "ids"));
|
||||||
|
if (!ids)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = JsonValueAsString(JsonGet(ids, 2, id, "event"));
|
||||||
|
ret = StrDuplicate(ret);
|
||||||
|
end:
|
||||||
|
DbUnlock(data->db, ref);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
ParseeEventFromSID(ParseeData *data, char *chat_id, char *id)
|
ParseeEventFromSID(ParseeData *data, char *chat_id, char *id)
|
||||||
{
|
{
|
||||||
|
|
@ -521,6 +722,38 @@ end:
|
||||||
DbUnlock(data->db, ref);
|
DbUnlock(data->db, ref);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
char *
|
||||||
|
ParseeDMEventFromSID(ParseeData *data, char *room_id, char *id)
|
||||||
|
{
|
||||||
|
DbRef *ref = NULL;
|
||||||
|
HashMap *j = NULL;
|
||||||
|
HashMap *ids = NULL;
|
||||||
|
char *ret = NULL;
|
||||||
|
if (!data || !room_id || !id)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref = DbLock(data->db, 3, "rooms", room_id, "data");
|
||||||
|
j = DbJson(ref);
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ids = JsonValueAsObject(HashMapGet(j, "stanzas"));
|
||||||
|
if (!ids)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = JsonValueAsString(JsonGet(ids, 2, id, "event"));
|
||||||
|
ret = StrDuplicate(ret);
|
||||||
|
end:
|
||||||
|
DbUnlock(data->db, ref);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
void
|
void
|
||||||
ParseeGlobalBan(ParseeData *data, char *user)
|
ParseeGlobalBan(ParseeData *data, char *user)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -550,6 +550,38 @@ ParseeSendPresence(ParseeData *data)
|
||||||
DbUnlock(data->db, ref);
|
DbUnlock(data->db, ref);
|
||||||
}
|
}
|
||||||
bool
|
bool
|
||||||
|
ParseeGetDMStanzaInfo(ParseeData *data, char *room_id, char *ev, char **st, char **se)
|
||||||
|
{
|
||||||
|
DbRef *ref = NULL;
|
||||||
|
HashMap *j = NULL;
|
||||||
|
HashMap *event = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
if (!data || !room_id || !ev || !st || !se)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref = DbLock(data->db, 3, "rooms", room_id, "data");
|
||||||
|
j = DbJson(ref);
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
event = JsonValueAsObject(JsonGet(j, 2, "events", ev));
|
||||||
|
if (!event)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
*st = StrDuplicate(JsonValueAsString(HashMapGet(event, "origin")));
|
||||||
|
*se = StrDuplicate(JsonValueAsString(HashMapGet(event, "sender")));
|
||||||
|
ret = true;
|
||||||
|
end:
|
||||||
|
DbUnlock(data->db, ref);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
bool
|
||||||
ParseeGetStanzaInfo(ParseeData *data, char *chat_id, char *ev, char **st, char **se)
|
ParseeGetStanzaInfo(ParseeData *data, char *chat_id, char *ev, char **st, char **se)
|
||||||
{
|
{
|
||||||
DbRef *ref = NULL;
|
DbRef *ref = NULL;
|
||||||
|
|
@ -582,6 +614,38 @@ end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
bool
|
bool
|
||||||
|
ParseeGetDMOrigin(ParseeData *data, char *room_id, char *ev, char **o)
|
||||||
|
{
|
||||||
|
DbRef *ref = NULL;
|
||||||
|
HashMap *j = NULL;
|
||||||
|
HashMap *event = NULL;
|
||||||
|
bool ret = false;
|
||||||
|
if (!data || !room_id || !ev || !o)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref = DbLock(data->db, 3, "rooms", room_id, "data");
|
||||||
|
j = DbJson(ref);
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
event = JsonValueAsObject(JsonGet(j, 2, "events", ev));
|
||||||
|
if (!event)
|
||||||
|
{
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
*o = StrDuplicate(JsonValueAsString(HashMapGet(event, "origin")));
|
||||||
|
ret = true;
|
||||||
|
end:
|
||||||
|
DbUnlock(data->db, ref);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
bool
|
||||||
ParseeGetOrigin(ParseeData *data, char *chat_id, char *ev, char **o)
|
ParseeGetOrigin(ParseeData *data, char *chat_id, char *ev, char **o)
|
||||||
{
|
{
|
||||||
DbRef *ref = NULL;
|
DbRef *ref = NULL;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
static HttpServer *server = NULL;
|
static HttpServer *server = NULL;
|
||||||
static pthread_t xmpp_thr;
|
static pthread_t xmpp_thr;
|
||||||
|
static bool valid = true;
|
||||||
static XMPPComponent *jabber = NULL;
|
static XMPPComponent *jabber = NULL;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -34,6 +35,7 @@ SignalHandler(int signal)
|
||||||
Log(LOG_INFO, "Killing thread...");
|
Log(LOG_INFO, "Killing thread...");
|
||||||
XMPPKillThread(jabber, "killer");
|
XMPPKillThread(jabber, "killer");
|
||||||
pthread_join(xmpp_thr, NULL);
|
pthread_join(xmpp_thr, NULL);
|
||||||
|
valid = false;
|
||||||
Log(LOG_INFO, "Stopping server...");
|
Log(LOG_INFO, "Stopping server...");
|
||||||
HttpServerStop(server);
|
HttpServerStop(server);
|
||||||
break;
|
break;
|
||||||
|
|
@ -50,6 +52,8 @@ ParseeInitialiseSignals(HttpServer *s, pthread_t xmpp, XMPPComponent *j)
|
||||||
xmpp_thr = xmpp;
|
xmpp_thr = xmpp;
|
||||||
jabber = j;
|
jabber = j;
|
||||||
|
|
||||||
|
valid = true;
|
||||||
|
|
||||||
sigAction.sa_handler = SignalHandler;
|
sigAction.sa_handler = SignalHandler;
|
||||||
sigfillset(&sigAction.sa_mask);
|
sigfillset(&sigAction.sa_mask);
|
||||||
sigAction.sa_flags = SA_RESTART;
|
sigAction.sa_flags = SA_RESTART;
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,18 @@
|
||||||
|
|
||||||
void
|
void
|
||||||
XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *edit)
|
XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *edit)
|
||||||
|
{
|
||||||
|
char *ident = StrRandom(32);
|
||||||
|
XMPPSendPlainID(comp, fr, to, msg, type, rst, rse, event_id, oob, edit, ident);
|
||||||
|
Free(ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
XMPPSendPlainID(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *edit, char *ident)
|
||||||
{
|
{
|
||||||
XMLElement *message, *body, *data, *parsee;
|
XMLElement *message, *body, *data, *parsee;
|
||||||
char *from;
|
char *from;
|
||||||
if (!comp || !fr || !to || !msg)
|
if (!comp || !fr || !to || !msg || !ident)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -23,6 +31,7 @@ XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, ch
|
||||||
XMLAddAttr(message, "from", (from = StrConcat(3, fr, "@", comp->host)));
|
XMLAddAttr(message, "from", (from = StrConcat(3, fr, "@", comp->host)));
|
||||||
XMLAddAttr(message, "to", to);
|
XMLAddAttr(message, "to", to);
|
||||||
XMLAddAttr(message, "type", type);
|
XMLAddAttr(message, "type", type);
|
||||||
|
XMLAddAttr(message, "id", ident);
|
||||||
|
|
||||||
body = XMLCreateTag("body");
|
body = XMLCreateTag("body");
|
||||||
data = XMLCreateText(oob ? oob : msg);
|
data = XMLCreateText(oob ? oob : msg);
|
||||||
|
|
@ -115,6 +124,8 @@ XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, ch
|
||||||
XMLAddChild(body, data);
|
XMLAddChild(body, data);
|
||||||
|
|
||||||
XMLEncode(comp->stream, message);
|
XMLEncode(comp->stream, message);
|
||||||
|
XMLEncode(StreamStdout(), message);
|
||||||
|
Log(LOG_INFO, "");
|
||||||
StreamFlush(comp->stream);
|
StreamFlush(comp->stream);
|
||||||
XMLFreeElement(message);
|
XMLFreeElement(message);
|
||||||
Free(from);
|
Free(from);
|
||||||
|
|
|
||||||
159
src/XMPPThread.c
159
src/XMPPThread.c
|
|
@ -15,15 +15,15 @@
|
||||||
#include <AS.h>
|
#include <AS.h>
|
||||||
|
|
||||||
#define IQ_ADVERT \
|
#define IQ_ADVERT \
|
||||||
AdvertiseSimple("http://jabber.org/protocol/caps") \
|
|
||||||
AdvertiseSimple("http://jabber.org/protocol/chatstates") \
|
AdvertiseSimple("http://jabber.org/protocol/chatstates") \
|
||||||
|
AdvertiseSimple("http://jabber.org/protocol/caps") \
|
||||||
|
AdvertiseSimple("urn:xmpp:avatar:metadata+notify") \
|
||||||
AdvertiseSimple("urn:xmpp:message-correct:0") \
|
AdvertiseSimple("urn:xmpp:message-correct:0") \
|
||||||
AdvertiseSimple("urn:xmpp:reactions:0") \
|
AdvertiseSimple("urn:xmpp:reactions:0") \
|
||||||
AdvertiseSimple("urn:xmpp:styling:0") \
|
AdvertiseSimple("urn:xmpp:styling:0") \
|
||||||
AdvertiseSimple("urn:xmpp:reply:0") \
|
AdvertiseSimple("urn:xmpp:reply:0") \
|
||||||
AdvertiseSimple("jabber:x:oob") \
|
AdvertiseSimple("jabber:x:oob") \
|
||||||
AdvertiseSimple("vcard-temp") \
|
AdvertiseSimple("vcard-temp") \
|
||||||
AdvertiseSimple("urn:xmpp:avatar:metadata+notify") \
|
|
||||||
AdvertiseSimple("jabber:iq:version") \
|
AdvertiseSimple("jabber:iq:version") \
|
||||||
AdvertiseSimple("urn:parsee:x-parsee:0") \
|
AdvertiseSimple("urn:parsee:x-parsee:0") \
|
||||||
AdvertiseSimple("urn:parsee:jealousy:0")
|
AdvertiseSimple("urn:parsee:jealousy:0")
|
||||||
|
|
@ -162,13 +162,112 @@ ParseeWakeupThread(void)
|
||||||
pthread_mutex_unlock(&cond_var_lock);
|
pthread_mutex_unlock(&cond_var_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static char *
|
||||||
ParseeDMHandler(char *room, char *from, XMLElement *data, const ParseeConfig *c)
|
ParseeGetBridgedRoom(ParseeData *data, XMLElement *stanza)
|
||||||
{
|
{
|
||||||
Free(ASSend(
|
char *to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to"));
|
||||||
c, room, from,
|
char *from = (HashMapGet(stanza->attrs, "from"));
|
||||||
"m.room.message", MatrixCreateMessage(data->data)
|
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;
|
||||||
|
}
|
||||||
|
static 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;
|
||||||
|
}
|
||||||
|
static char *
|
||||||
|
ParseeGetReactedEvent(ParseeData *data, XMLElement *stanza)
|
||||||
|
{
|
||||||
|
XMLElement *reactions = XMLookForTKV(stanza,
|
||||||
|
"reactions", "xmlns", "urn:xmpp:reactions:0"
|
||||||
|
);
|
||||||
|
char *from = (HashMapGet(stanza->attrs, "from"));
|
||||||
|
char *reacted_id = reactions ? HashMapGet(reactions->attrs, "id") : NULL;
|
||||||
|
|
||||||
|
return ParseeGetEventFromID(data, stanza, reacted_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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);
|
||||||
|
char *o_id_str = XMPPGetOriginID(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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: Clean up all of this. We are currently separating DMs from MUCs,
|
/* TODO: Clean up all of this. We are currently separating DMs from MUCs,
|
||||||
|
|
@ -225,7 +324,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: On semi-anonymous MUCs, it might be preferable to use a
|
/* TODO: On semi-anonymous MUCs, it might be preferable to use a
|
||||||
* form of the occupant ID as the base, as it is more unique, and
|
* form of the occupant ID as the base, as it is more unique, and
|
||||||
* less prone to trigger the character limit on Matrix.
|
* less prone to trigger the character limit on Matrix.
|
||||||
|
|
@ -237,12 +335,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
room = ParseeFindDMRoom(args, to, from);
|
room = ParseeFindDMRoom(args, to, from);
|
||||||
data = ArrayGet(body->children, 0);
|
data = ArrayGet(body->children, 0);
|
||||||
|
|
||||||
chat_id = ParseeGetFromMUCID(args, from);
|
mroom_id = ParseeGetBridgedRoom(args, stanza);
|
||||||
mroom_id = ParseeGetRoomID(args, chat_id);
|
|
||||||
if (room)
|
|
||||||
{
|
|
||||||
ParseeDMHandler(room, from_matrix, data, args->config);
|
|
||||||
}
|
|
||||||
if (mroom_id && !XMPPIsParseeStanza(stanza))
|
if (mroom_id && !XMPPIsParseeStanza(stanza))
|
||||||
{
|
{
|
||||||
char *res = ParseeGetResource(from);
|
char *res = ParseeGetResource(from);
|
||||||
|
|
@ -253,13 +346,24 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
char *event_id = NULL;
|
char *event_id = NULL;
|
||||||
char *replaced = XMPPGetReplacedID(stanza);
|
char *replaced = XMPPGetReplacedID(stanza);
|
||||||
char *reply_to = XMPPGetReply(stanza);
|
char *reply_to = XMPPGetReply(stanza);
|
||||||
|
bool chat = false;
|
||||||
|
|
||||||
if (ParseeVerifyStanza(args, chat_id, s_id_str) && !replaced)
|
if (StrEquals(HashMapGet(stanza->attrs, "type"), "chat"))
|
||||||
|
{
|
||||||
|
Free(encoded);
|
||||||
|
encoded = StrDuplicate(from_matrix);
|
||||||
|
chat = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ParseeVerifyAllStanza(args, stanza) && !replaced)
|
||||||
{
|
{
|
||||||
XMLElement *oob, *oob_data;
|
XMLElement *oob, *oob_data;
|
||||||
|
|
||||||
ASRegisterUser(args->config, encoded);
|
ASRegisterUser(args->config, encoded);
|
||||||
|
if (!chat)
|
||||||
|
{
|
||||||
ASSetName(args->config, encoded, res);
|
ASSetName(args->config, encoded, res);
|
||||||
|
}
|
||||||
ASInvite(args->config, mroom_id, encoded);
|
ASInvite(args->config, mroom_id, encoded);
|
||||||
ASJoin(args->config, mroom_id, encoded);
|
ASJoin(args->config, mroom_id, encoded);
|
||||||
|
|
||||||
|
|
@ -290,7 +394,7 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
char *reacted_id = HashMapGet(reactions->attrs, "id");
|
char *reacted_id = HashMapGet(reactions->attrs, "id");
|
||||||
Array *react_child = reactions->children;
|
Array *react_child = reactions->children;
|
||||||
size_t reacts = ArraySize(react_child);
|
size_t reacts = ArraySize(react_child);
|
||||||
event_id = ParseeEventFromSID(args, chat_id, reacted_id);
|
event_id = ParseeGetReactedEvent(args, stanza);
|
||||||
for (i = 0; i < reacts; i++)
|
for (i = 0; i < reacts; i++)
|
||||||
{
|
{
|
||||||
XMLElement *reaction, *react_data;
|
XMLElement *reaction, *react_data;
|
||||||
|
|
@ -311,15 +415,13 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
{
|
{
|
||||||
/* TODO: Use HTML-formatted bodies, and respect the fallback
|
/* TODO: Use HTML-formatted bodies, and respect the fallback
|
||||||
* trims the stanza provides us if possible. Element does
|
* trims the stanza provides us if possible. Element does
|
||||||
* not like raw bodies on replies. Go figure. */
|
* not like raw bodies on replies too. Go figure. */
|
||||||
size_t off =
|
size_t off =
|
||||||
reply_to ? ParseeFindDatastart(data->data) : 0;
|
reply_to ? ParseeFindDatastart(data->data) : 0;
|
||||||
HashMap *ev = MatrixCreateMessage(data->data + off);
|
HashMap *ev = MatrixCreateMessage(data->data + off);
|
||||||
if (reply_to)
|
if (reply_to)
|
||||||
{
|
{
|
||||||
char *reply_id = ParseeEventFromSID(
|
char *reply_id = ParseeGetEventFromID(args, stanza, reply_to);
|
||||||
args, chat_id, reply_to
|
|
||||||
);
|
|
||||||
MatrixSetReply(ev, reply_id);
|
MatrixSetReply(ev, reply_id);
|
||||||
Free(reply_id);
|
Free(reply_id);
|
||||||
}
|
}
|
||||||
|
|
@ -328,16 +430,17 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
"m.room.message", ev
|
"m.room.message", ev
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ParseePushStanza(args, chat_id, s_id_str, id_str, event_id, from);
|
ParseePushAllStanza(args, stanza, event_id);
|
||||||
Free(event_id);
|
Free(event_id);
|
||||||
}
|
}
|
||||||
else if (replaced)
|
else if (replaced)
|
||||||
{
|
{
|
||||||
event_id = ParseeEventFromID(args, chat_id, replaced);
|
event_id = ParseeGetEventFromID(args, stanza, replaced);
|
||||||
Free(ASSend(
|
Free(ASSend(
|
||||||
args->config, mroom_id, encoded,
|
args->config, mroom_id, encoded,
|
||||||
"m.room.message", MatrixCreateReplace(event_id, data->data)
|
"m.room.message", MatrixCreateReplace(event_id, data->data)
|
||||||
));
|
));
|
||||||
|
ParseePushAllStanza(args, stanza, event_id);
|
||||||
|
|
||||||
Free(event_id);
|
Free(event_id);
|
||||||
}
|
}
|
||||||
|
|
@ -345,19 +448,16 @@ MessageStanza(ParseeData *args, XMLElement *stanza)
|
||||||
Free(res);
|
Free(res);
|
||||||
Free(encoded);
|
Free(encoded);
|
||||||
}
|
}
|
||||||
else if (mroom_id)
|
else
|
||||||
{
|
{
|
||||||
XMLElement *parsee = XMLookForUnique(stanza, "x-parsee");
|
XMLElement *parsee = XMLookForUnique(stanza, "x-parsee");
|
||||||
XMLElement *event = XMLookForUnique(parsee, "event-id");
|
XMLElement *event = XMLookForUnique(parsee, "event-id");
|
||||||
XMLElement *e_d = ArrayGet(event ? event->children : NULL, 0);
|
XMLElement *e_d = ArrayGet(event ? event->children : NULL, 0);
|
||||||
char *s_id_str = XMPPGetStanzaID(stanza);
|
char *s_id_str = XMPPGetStanzaID(stanza);
|
||||||
char *id_str = HashMapGet(stanza->attrs, "id");
|
char *id_str = HashMapGet(stanza->attrs, "id");
|
||||||
if (ParseeVerifyStanza(args, chat_id, s_id_str))
|
|
||||||
{
|
ParseePushAllStanza(args, stanza, e_d->data);
|
||||||
ParseePushStanza(args, chat_id, s_id_str, id_str, e_d->data, from);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Free(chat_id);
|
|
||||||
Free(mroom_id);
|
Free(mroom_id);
|
||||||
Free(from_matrix);
|
Free(from_matrix);
|
||||||
Free(decode_from);
|
Free(decode_from);
|
||||||
|
|
@ -579,6 +679,7 @@ ParseeXMPPThread(void *argp)
|
||||||
const char *killer = "killer";
|
const char *killer = "killer";
|
||||||
const char *suspend="suspend";
|
const char *suspend="suspend";
|
||||||
from = HashMapGet(stanza->attrs, "from");
|
from = HashMapGet(stanza->attrs, "from");
|
||||||
|
Log(LOG_INFO, "Killer.");
|
||||||
if (!strncmp(from, killer, strlen(killer)))
|
if (!strncmp(from, killer, strlen(killer)))
|
||||||
{
|
{
|
||||||
XMLFreeElement(stanza);
|
XMLFreeElement(stanza);
|
||||||
|
|
|
||||||
|
|
@ -159,13 +159,16 @@ extern char * ParseeGetMUCID(ParseeData *, char *chat_id);
|
||||||
|
|
||||||
/* Pushes a stanza ID to a chat ID */
|
/* Pushes a stanza ID to a chat ID */
|
||||||
extern void ParseePushStanza(ParseeData *, char *chat_id, char *stanza_id, char *origin_id, char *event, char *sender);
|
extern void ParseePushStanza(ParseeData *, char *chat_id, char *stanza_id, char *origin_id, char *event, char *sender);
|
||||||
|
extern void ParseePushDMStanza(ParseeData *, char *room_id, char *stanza_id, char *origin_id, char *event, char *sender);
|
||||||
|
|
||||||
/* Checks if a stanza is not duplicated in a chat ID */
|
/* Checks if a stanza is not duplicated in a chat ID */
|
||||||
extern bool ParseeVerifyStanza(ParseeData *, char *chat_id, char *stanza_id);
|
extern bool ParseeVerifyStanza(ParseeData *, char *chat_id, char *stanza_id);
|
||||||
|
|
||||||
/* Gets the stanza ID and sender of an event */
|
/* Gets the stanza ID and sender of an event */
|
||||||
extern bool ParseeGetStanzaInfo(ParseeData *, char *c_id, char *e, char **st, char **se);
|
extern bool ParseeGetStanzaInfo(ParseeData *, char *c_id, char *e, char **st, char **se);
|
||||||
|
extern bool ParseeGetDMStanzaInfo(ParseeData *, char *r_id, char *e, char **st, char **se);
|
||||||
extern bool ParseeGetOrigin(ParseeData *data, char *chat_id, char *ev, char **o);
|
extern bool ParseeGetOrigin(ParseeData *data, char *chat_id, char *ev, char **o);
|
||||||
|
extern bool ParseeGetDMOrigin(ParseeData *data, char *chat_id, char *ev, char **o);
|
||||||
|
|
||||||
/* Sends presence requests for every MUC around as a fake JID */
|
/* Sends presence requests for every MUC around as a fake JID */
|
||||||
extern void ParseeSendPresence(ParseeData *);
|
extern void ParseeSendPresence(ParseeData *);
|
||||||
|
|
@ -186,6 +189,9 @@ extern char * ParseeXMPPify(HashMap *event);
|
||||||
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 * 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 */
|
/* 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);
|
||||||
|
|
||||||
|
|
@ -201,4 +207,7 @@ extern void ParseeGlobalBan(ParseeData *, char *user);
|
||||||
/* Verifies if a user was globally banned. If so, then apply actions to the
|
/* Verifies if a user was globally banned. If so, then apply actions to the
|
||||||
* room ID */
|
* room ID */
|
||||||
extern bool ParseeManageBan(ParseeData *, char *user, char *room);
|
extern bool ParseeManageBan(ParseeData *, char *user, char *room);
|
||||||
|
|
||||||
|
/* Same as ParseeVerifyStanza, but DMs */
|
||||||
|
extern bool ParseeVerifyDMStanza(ParseeData *data, char *room_id, char *id);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,11 @@ typedef struct ParseeCmdArg {
|
||||||
"set-pl", CmdSetPL, \
|
"set-pl", CmdSetPL, \
|
||||||
"Sets the power level in a Parsee room" \
|
"Sets the power level in a Parsee room" \
|
||||||
) \
|
) \
|
||||||
|
X_COMMAND( \
|
||||||
|
"set-min-pl", CmdSetMin, \
|
||||||
|
"Sets the power level to send a specific event " \
|
||||||
|
"in a Parsee room" \
|
||||||
|
) \
|
||||||
X_COMMAND( \
|
X_COMMAND( \
|
||||||
"help", CmdHelp, \
|
"help", CmdHelp, \
|
||||||
"Shows the command list" \
|
"Shows the command list" \
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ 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, char *oob, char *id);
|
extern void XMPPSendPlain(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *id);
|
||||||
|
extern void XMPPSendPlainID(XMPPComponent *comp, char *fr, char *to, char *msg, char *type, char *rst, char *rse, char *event_id, char *oob, char *id, char *sid);
|
||||||
|
|
||||||
/* Closes a raw component stream. */
|
/* Closes a raw component stream. */
|
||||||
extern void XMPPEndCompStream(XMPPComponent *stream);
|
extern void XMPPEndCompStream(XMPPComponent *stream);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue