mirror of
https://forge.fsky.io/lda/Parsee.git
synced 2026-03-13 18:35:11 +00:00
[MOD/WIP] Continue XEP-0421
This commit is contained in:
parent
63c1bc819e
commit
c9f8d69802
8 changed files with 120 additions and 66 deletions
|
|
@ -515,7 +515,7 @@ XMPPSendDisco(XMPPComponent *jabber, char *from, char *to)
|
||||||
pthread_mutex_unlock(&jabber->write_lock);
|
pthread_mutex_unlock(&jabber->write_lock);
|
||||||
XMLFreeElement(iq);
|
XMLFreeElement(iq);
|
||||||
|
|
||||||
ret = ParseeAwaitStanza(identifier, 250);
|
ret = ParseeAwaitStanza(identifier, 5000);
|
||||||
Free(identifier);
|
Free(identifier);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,12 +43,19 @@ NoflyCallback(XMPPCommandManager *m, char *from, XMLElement *form, XMLElement *o
|
||||||
XMLAddAttr(x, "type", "result");
|
XMLAddAttr(x, "type", "result");
|
||||||
{
|
{
|
||||||
DbRef *ref = DbLock(data->db, 1, "global_bans");
|
DbRef *ref = DbLock(data->db, 1, "global_bans");
|
||||||
HashMap *bans = DbJson(ref);
|
HashMap *bans;
|
||||||
char *banned, *reason;
|
char *banned, *reason;
|
||||||
JsonValue *ban_val;
|
JsonValue *ban_val;
|
||||||
reported = XMLCreateTag("reported");
|
reported = XMLCreateTag("reported");
|
||||||
XMLAddChild(x, reported);
|
XMLAddChild(x, reported);
|
||||||
|
|
||||||
|
if (!ref)
|
||||||
|
{
|
||||||
|
ref = DbCreate(data->db, 1, "global_bans");
|
||||||
|
}
|
||||||
|
|
||||||
|
bans = DbJson(ref);
|
||||||
|
|
||||||
/* Report */
|
/* Report */
|
||||||
Report("ban", "Banned glob");
|
Report("ban", "Banned glob");
|
||||||
Report("reason", "Reason for the nofly");
|
Report("reason", "Reason for the nofly");
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include <Cytoplasm/Memory.h>
|
#include <Cytoplasm/Memory.h>
|
||||||
#include <Cytoplasm/Str.h>
|
#include <Cytoplasm/Str.h>
|
||||||
#include <Cytoplasm/Log.h>
|
#include <Cytoplasm/Log.h>
|
||||||
|
#include <Cytoplasm/Sha.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
@ -116,6 +117,7 @@ ParseeVerifyAllStanza(ParseeData *args, XMLElement *stanza)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Cache this information. */
|
||||||
bool
|
bool
|
||||||
ServerHasXEP421(ParseeData *data, char *from)
|
ServerHasXEP421(ParseeData *data, char *from)
|
||||||
{
|
{
|
||||||
|
|
@ -153,32 +155,84 @@ ServerHasXEP421(ParseeData *data, char *from)
|
||||||
Free(server);
|
Free(server);
|
||||||
return ret;
|
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->homeserver_host
|
||||||
|
);
|
||||||
|
Free(sha);
|
||||||
|
return mxid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Shove that function everywhere one can see fit. */
|
||||||
char *
|
char *
|
||||||
ParseeGetBridgedUser(ParseeData *data, XMLElement *stanza)
|
ParseeGetBridgedUserI(ParseeData *data, XMLElement *stanza, char *force)
|
||||||
{
|
{
|
||||||
char *user, *xmpp_from, *type;
|
char *user, *xmpp_from, *type;
|
||||||
char *decode_from;
|
char *decode_from, *occ_id = NULL;
|
||||||
|
bool is_chat, has_anon = false, is_anon = false;
|
||||||
|
|
||||||
if (!data || !stanza)
|
if (!data || !stanza)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xmpp_from = HashMapGet(stanza->attrs, "from");
|
xmpp_from = force ? force : HashMapGet(stanza->attrs, "from");
|
||||||
type = HashMapGet(stanza->attrs, "type");
|
type = HashMapGet(stanza->attrs, "type");
|
||||||
decode_from = ParseeLookupJID(xmpp_from);
|
decode_from = ParseeLookupJID(xmpp_from);
|
||||||
|
|
||||||
/* TODO: On semi-anonymous MUCs, it might be preferable to use a
|
is_chat = StrEquals(type, "chat");
|
||||||
* form of the occupant ID as the base, as it is more unique, and
|
if (!is_chat)
|
||||||
* less prone to trigger the character limit on Matrix.
|
{
|
||||||
* I'll need to detect these first....
|
has_anon = ServerHasXEP421(data, xmpp_from);
|
||||||
*
|
is_anon = has_anon && StrEquals(xmpp_from, decode_from);
|
||||||
* See: https://xmpp.org/extensions/xep-0421.html */
|
}
|
||||||
|
|
||||||
|
if (is_anon)
|
||||||
|
{
|
||||||
|
XMLElement *occupant;
|
||||||
|
occupant = XMLookForTKV(
|
||||||
|
stanza, "occupant-id",
|
||||||
|
"xmlns", "urn:xmpp:occupant-id:0"
|
||||||
|
);
|
||||||
|
occ_id = occupant ? HashMapGet(occupant->attrs, "id") : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!occ_id)
|
||||||
|
{
|
||||||
user = ParseeEncodeJID(
|
user = ParseeEncodeJID(
|
||||||
data->config,
|
data->config,
|
||||||
decode_from,
|
decode_from,
|
||||||
StrEquals(type, "chat")
|
type ? is_chat : false
|
||||||
);
|
);
|
||||||
Free(decode_from);
|
Free(decode_from);
|
||||||
return user;
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
Free(decode_from);
|
||||||
|
return ScrambleOID(data, occ_id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -229,15 +229,6 @@ ParseeXMPPThread(void *argp)
|
||||||
XMLElement *
|
XMLElement *
|
||||||
ParseeAwaitStanza(char *identifier, int64_t timeout)
|
ParseeAwaitStanza(char *identifier, int64_t timeout)
|
||||||
{
|
{
|
||||||
XMPPAwait *awa;
|
|
||||||
XMLElement *stanza;
|
|
||||||
struct timespec ts;
|
|
||||||
|
|
||||||
if (!identifier)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: You may be wondering _why_ I am using stdlib's malloc, instead of
|
/* XXX: You may be wondering _why_ I am using stdlib's malloc, instead of
|
||||||
* Cytoplasm's Malloc wrapper(which are essentially the same thing, plus
|
* Cytoplasm's Malloc wrapper(which are essentially the same thing, plus
|
||||||
* some memchecking as of now), or the stack, as done previously.
|
* some memchecking as of now), or the stack, as done previously.
|
||||||
|
|
@ -246,15 +237,26 @@ ParseeAwaitStanza(char *identifier, int64_t timeout)
|
||||||
* since, as I said, it is as of now just malloc with extra metadata prepended
|
* since, as I said, it is as of now just malloc with extra metadata prepended
|
||||||
* to it. A _guess_ may be that the metadata makes everything unaligned, which,
|
* to it. A _guess_ may be that the metadata makes everything unaligned, which,
|
||||||
* just sounds silly. pthreads should be able to cope fine with that, I think.
|
* just sounds silly. pthreads should be able to cope fine with that, I think.
|
||||||
* - The stack seems to be a prime candidate to cause a stack corruption, which
|
|
||||||
* puzzled me for a comically long while("why is the value being swapped for
|
|
||||||
* the key?" "why does duplicating twice cause the former problem to disappear,
|
|
||||||
* but still obviously creating another one?", ...).
|
|
||||||
*
|
*
|
||||||
* I am open to issues talking about such fun behaviour and ideas to fix this.
|
* I am open to issues talking about such fun behaviour and ideas to fix this.
|
||||||
* This is a bodge, and potentially a problem, or vulnerability with Cytoplasm/
|
* This is a bodge, and potentially a problem, or vulnerability with Cytoplasm/
|
||||||
* Parsee. As long as it isn't "use Rust". Please don't say that. */
|
* Parsee. As long as it isn't "use Rust". Please don't say that. */
|
||||||
awa = malloc(sizeof(XMPPAwait));
|
XMPPAwait awa = { 0 };
|
||||||
|
XMLElement *stanza;
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
if (!identifier)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&await_lock);
|
||||||
|
if (HashMapGet(await_table, identifier))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&await_lock);
|
||||||
|
|
||||||
|
|
||||||
/* Convert into an absolute timeout.
|
/* Convert into an absolute timeout.
|
||||||
* =================================
|
* =================================
|
||||||
|
|
@ -282,29 +284,24 @@ ParseeAwaitStanza(char *identifier, int64_t timeout)
|
||||||
|
|
||||||
pthread_mutex_lock(&await_lock);
|
pthread_mutex_lock(&await_lock);
|
||||||
|
|
||||||
pthread_cond_init(&awa->condition, NULL);
|
pthread_cond_init(&awa.condition, NULL);
|
||||||
pthread_mutex_init(&awa->cond_lock, NULL);
|
pthread_mutex_init(&awa.cond_lock, NULL);
|
||||||
awa->stanza = NULL;
|
awa.stanza = NULL;
|
||||||
|
|
||||||
if (HashMapGet(await_table, identifier))
|
HashMapSet(await_table, identifier, &awa);
|
||||||
{
|
|
||||||
HashMapDelete(await_table, identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMapSet(await_table, identifier, awa);
|
|
||||||
pthread_mutex_unlock(&await_lock);
|
pthread_mutex_unlock(&await_lock);
|
||||||
|
|
||||||
pthread_mutex_lock(&awa->cond_lock);
|
pthread_mutex_lock(&awa.cond_lock);
|
||||||
while (!awa->stanza)
|
while (!awa.stanza)
|
||||||
{
|
{
|
||||||
int code;
|
int code;
|
||||||
|
|
||||||
if (timeout <= 0)
|
if (timeout <= 0)
|
||||||
{
|
{
|
||||||
pthread_cond_wait(&awa->condition, &awa->cond_lock);
|
pthread_cond_wait(&awa.condition, &awa.cond_lock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
code = pthread_cond_timedwait(&awa->condition, &awa->cond_lock, &ts);
|
code = pthread_cond_timedwait(&awa.condition, &awa.cond_lock, &ts);
|
||||||
if (code == ETIMEDOUT)
|
if (code == ETIMEDOUT)
|
||||||
{
|
{
|
||||||
/* Timeout detected, give up regardless of the status of our
|
/* Timeout detected, give up regardless of the status of our
|
||||||
|
|
@ -319,11 +316,10 @@ ParseeAwaitStanza(char *identifier, int64_t timeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stanza = awa->stanza;
|
stanza = awa.stanza;
|
||||||
pthread_mutex_unlock(&awa->cond_lock);
|
pthread_mutex_unlock(&awa.cond_lock);
|
||||||
|
|
||||||
pthread_cond_destroy(&awa->condition);
|
pthread_cond_destroy(&awa.condition);
|
||||||
pthread_mutex_destroy(&awa->cond_lock);
|
pthread_mutex_destroy(&awa.cond_lock);
|
||||||
free(awa);
|
|
||||||
return stanza;
|
return stanza;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ IQResult(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||||
mxc = ASUpload(args->config, datastream, length, "image/png");
|
mxc = ASUpload(args->config, datastream, length, "image/png");
|
||||||
|
|
||||||
jid = ParseeLookupJID(from);
|
jid = ParseeLookupJID(from);
|
||||||
from_matrix = ParseeEncodeJID(args->config, jid, false);
|
from_matrix = ParseeGetBridgedUser(args, stanza);
|
||||||
ASSetAvatar(args->config, from_matrix, mxc);
|
ASSetAvatar(args->config, from_matrix, mxc);
|
||||||
|
|
||||||
JsonValueFree(JsonSet(
|
JsonValueFree(JsonSet(
|
||||||
|
|
|
||||||
|
|
@ -148,11 +148,6 @@ MessageStanza(ParseeData *args, XMLElement *stanza, XMPPThread *thr)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ServerHasXEP421(args, HashMapGet(stanza->attrs, "from")))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to"));
|
to = ParseeDecodeMXID(HashMapGet(stanza->attrs, "to"));
|
||||||
decode_from = ParseeLookupJID(from);
|
decode_from = ParseeLookupJID(from);
|
||||||
from_matrix = ParseeEncodeJID(args->config, decode_from, true);
|
from_matrix = ParseeEncodeJID(args->config, decode_from, true);
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
|
||||||
char *from = NULL;
|
char *from = NULL;
|
||||||
char *type = HashMapGet(stanza->attrs, "type");
|
char *type = HashMapGet(stanza->attrs, "type");
|
||||||
char *room = ParseeGetBridgedRoom(args, stanza);
|
char *room = ParseeGetBridgedRoom(args, stanza);
|
||||||
char *decode_from = ParseeLookupJID(oid);
|
char *decode_from, *real_matrix;
|
||||||
char *real_matrix = ParseeDecodeMXID(decode_from);
|
|
||||||
char *matrix_user_pl = ParseeEncodeJID(args->config, trim, false);
|
char *matrix_user_pl = ParseeEncodeJID(args->config, trim, false);
|
||||||
char *affiliation = HashMapGet(item->attrs, "affiliation");
|
char *affiliation = HashMapGet(item->attrs, "affiliation");
|
||||||
int power_level = 0;
|
int power_level = 0;
|
||||||
|
|
@ -85,10 +84,18 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
|
||||||
|
|
||||||
Free(trim);
|
Free(trim);
|
||||||
|
|
||||||
|
if (jid)
|
||||||
|
{
|
||||||
|
ParseePushJIDTable(oid, jid);
|
||||||
|
}
|
||||||
|
decode_from = ParseeLookupJID(oid);
|
||||||
|
real_matrix = ParseeDecodeMXID(decode_from);
|
||||||
|
|
||||||
if (!real_matrix || *real_matrix != '@')
|
if (!real_matrix || *real_matrix != '@')
|
||||||
{
|
{
|
||||||
Free(real_matrix);
|
Free(real_matrix);
|
||||||
real_matrix = ParseeEncodeJID(args->config, decode_from, false);
|
/*real_matrix = ParseeEncodeJID(args->config, decode_from, false);*/
|
||||||
|
real_matrix = ParseeGetBridgedUserI(args, stanza, oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StrEquals(affiliation, "owner"))
|
if (StrEquals(affiliation, "owner"))
|
||||||
|
|
@ -163,10 +170,6 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jid)
|
|
||||||
{
|
|
||||||
ParseePushJIDTable(oid, jid);
|
|
||||||
}
|
|
||||||
|
|
||||||
Free(from);
|
Free(from);
|
||||||
Free(decode_from);
|
Free(decode_from);
|
||||||
|
|
@ -179,8 +182,7 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
|
||||||
{
|
{
|
||||||
XMLElement *status_data = ArrayGet(status->children, 0);
|
XMLElement *status_data = ArrayGet(status->children, 0);
|
||||||
char *decode_from = ParseeLookupJID(oid);
|
char *decode_from = ParseeLookupJID(oid);
|
||||||
char *trimmed = ParseeTrimJID(decode_from);
|
char *from_matrix = ParseeGetBridgedUser(args, stanza);
|
||||||
char *from_matrix = ParseeEncodeJID(args->config, trimmed, false);
|
|
||||||
char *status_str = NULL;
|
char *status_str = NULL;
|
||||||
if (status_data)
|
if (status_data)
|
||||||
{
|
{
|
||||||
|
|
@ -199,7 +201,6 @@ PresenceStanza(ParseeData *args, XMLElement *stanza)
|
||||||
|
|
||||||
Free(decode_from);
|
Free(decode_from);
|
||||||
Free(from_matrix);
|
Free(from_matrix);
|
||||||
Free(trimmed);
|
|
||||||
}
|
}
|
||||||
if (vc)
|
if (vc)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -78,4 +78,5 @@ void PresenceStanza(ParseeData *args, XMLElement *stanza);
|
||||||
|
|
||||||
bool ServerHasXEP421(ParseeData *data, char *from);
|
bool ServerHasXEP421(ParseeData *data, char *from);
|
||||||
|
|
||||||
char * ParseeGetBridgedUser(ParseeData *data, XMLElement *stanza);
|
char * ParseeGetBridgedUserI(ParseeData *data, XMLElement *stanza, char *force);
|
||||||
|
#define ParseeGetBridgedUser(data, stanza) ParseeGetBridgedUserI(data, stanza, NULL)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue