forked from Telodendria/Telodendria
Compare commits
No commits in common. "a77be8b43730a1a871024212dfcf3ffa86b6249c" and "19359045e94badf6992f6ab83ca3fbdeb5797ec6" have entirely different histories.
a77be8b437
...
19359045e9
12 changed files with 106 additions and 370 deletions
11
configure
vendored
11
configure
vendored
|
@ -231,19 +231,15 @@ compile_schema() {
|
||||||
install_out() {
|
install_out() {
|
||||||
src="$1"
|
src="$1"
|
||||||
out="$2"
|
out="$2"
|
||||||
dir=$(dirname "$out")
|
|
||||||
|
|
||||||
echo "${TAB}mkdir -p \"$dir\""
|
echo "${TAB}install -D \"$src\" \"$out\""
|
||||||
echo "${TAB}cp \"$src\" \"$out\""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
install_man() {
|
install_man() {
|
||||||
src="${OUT}/man/man3/${BIN_NAME}-$(basename $1 .h).3"
|
src="${OUT}/man/man3/${BIN_NAME}-$(basename $1 .h).3"
|
||||||
out="$2"
|
out="$2"
|
||||||
dir=$(dirname "$out")
|
|
||||||
|
|
||||||
echo "${TAB}mkdir -p \"$dir\""
|
echo "${TAB}install -D \"$src\" \"$out\""
|
||||||
echo "${TAB}cp \"$src\" \"$out\""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uninstall_out() {
|
uninstall_out() {
|
||||||
|
@ -291,8 +287,7 @@ ${TAB}done
|
||||||
${BIN_NAME}: ${OUT}/bin/${BIN_NAME}
|
${BIN_NAME}: ${OUT}/bin/${BIN_NAME}
|
||||||
|
|
||||||
install: ${BIN_NAME}
|
install: ${BIN_NAME}
|
||||||
${TAB}mkdir -p \$(PREFIX)/bin
|
${TAB}install -D ${OUT}/bin/${BIN_NAME} \$(PREFIX)/bin/${BIN_NAME}
|
||||||
${TAB}cp ${OUT}/bin/${BIN_NAME} \$(PREFIX)/bin/${BIN_NAME}
|
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
${TAB}rm \$(PREFIX)/bin/${BIN_NAME}
|
${TAB}rm \$(PREFIX)/bin/${BIN_NAME}
|
||||||
|
|
|
@ -46,7 +46,7 @@ HtmlBegin(Stream * stream, char *title)
|
||||||
"<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"
|
"<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"
|
||||||
"<title>%s | Telodendria</title>"
|
"<title>%s | Telodendria</title>"
|
||||||
"<link rel=\"stylesheet\" href=\"/_matrix/static/telodendria.css\">"
|
"<link rel=\"stylesheet\" href=\"/_matrix/static/telodendria.css\">"
|
||||||
"<script src=\"/_matrix/static/telodendria.js\"></script>"
|
"<script src=\"/_matrix/static/telodendria.js\"></script>"
|
||||||
"</head>"
|
"</head>"
|
||||||
"<body>"
|
"<body>"
|
||||||
"<pre class=\"logo\">"
|
"<pre class=\"logo\">"
|
||||||
|
|
|
@ -297,8 +297,7 @@ start:
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tConfig.log.timestampFormat ||
|
if (!tConfig.log.timestampFormat || !StrEquals(tConfig.log.timestampFormat, "default"))
|
||||||
!StrEquals(tConfig.log.timestampFormat, "default"))
|
|
||||||
{
|
{
|
||||||
LogConfigTimeStampFormatSet(LogConfigGlobal(), tConfig.log.timestampFormat);
|
LogConfigTimeStampFormatSet(LogConfigGlobal(), tConfig.log.timestampFormat);
|
||||||
}
|
}
|
||||||
|
|
291
src/Room.c
291
src/Room.c
|
@ -126,7 +126,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
JsonValueFree(HashMapSet(content, key, JsonValueDuplicate(val)));
|
JsonValueFree(HashMapSet(content, key, JsonValueDuplicate(val)));
|
||||||
}
|
}
|
||||||
event = RoomEventCreate(sender_str, "m.room.create", "", content);
|
event = RoomEventCreate(sender_str, "m.room.create", "", content);
|
||||||
JsonFree(RoomEventSend(room, event, NULL));
|
JsonFree(RoomEventSend(room, event));
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
UserAddJoin(user, room->id);
|
UserAddJoin(user, room->id);
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
content = HashMapCreate();
|
content = HashMapCreate();
|
||||||
JsonSet(content, JsonValueString("join"), 1, "membership");
|
JsonSet(content, JsonValueString("join"), 1, "membership");
|
||||||
event = RoomEventCreate(sender_str, "m.room.member", sender_str, content);
|
event = RoomEventCreate(sender_str, "m.room.member", sender_str, content);
|
||||||
JsonFree(RoomEventSend(room, event, NULL));
|
JsonFree(RoomEventSend(room, event));
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
|
|
||||||
/* m.room.power_levels */
|
/* m.room.power_levels */
|
||||||
|
@ -155,7 +155,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
HashMapSet(content, key, JsonValueDuplicate(val));
|
HashMapSet(content, key, JsonValueDuplicate(val));
|
||||||
}
|
}
|
||||||
event = RoomEventCreate(sender_str, "m.room.power_levels", "", content);
|
event = RoomEventCreate(sender_str, "m.room.power_levels", "", content);
|
||||||
JsonFree(RoomEventSend(room, event, NULL));
|
JsonFree(RoomEventSend(room, event));
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
|
|
||||||
/* Presets */
|
/* Presets */
|
||||||
|
@ -203,7 +203,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
event = RoomEventCreate( \
|
event = RoomEventCreate( \
|
||||||
sender_str, \
|
sender_str, \
|
||||||
"m.room." #p, "", content); \
|
"m.room." #p, "", content); \
|
||||||
JsonFree(RoomEventSend(room, event, NULL)); \
|
JsonFree(RoomEventSend(room, event)); \
|
||||||
JsonFree(event); \
|
JsonFree(event); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
@ -227,7 +227,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
}
|
}
|
||||||
HashMapSet(rseObject, "sender", JsonValueString(sender_str));
|
HashMapSet(rseObject, "sender", JsonValueString(sender_str));
|
||||||
|
|
||||||
JsonFree(RoomEventSend(room, rseObject, NULL));
|
JsonFree(RoomEventSend(room, rseObject));
|
||||||
JsonFree(rseObject);
|
JsonFree(rseObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
content = HashMapCreate();
|
content = HashMapCreate();
|
||||||
JsonSet(content, JsonValueString(req->name), 1, "name");
|
JsonSet(content, JsonValueString(req->name), 1, "name");
|
||||||
event = RoomEventCreate(sender_str, "m.room.name", "", content);
|
event = RoomEventCreate(sender_str, "m.room.name", "", content);
|
||||||
JsonFree(RoomEventSend(room, event, NULL));
|
JsonFree(RoomEventSend(room, event));
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
}
|
}
|
||||||
if (req->topic)
|
if (req->topic)
|
||||||
|
@ -245,7 +245,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
content = HashMapCreate();
|
content = HashMapCreate();
|
||||||
JsonSet(content, JsonValueString(req->topic), 1, "topic");
|
JsonSet(content, JsonValueString(req->topic), 1, "topic");
|
||||||
event = RoomEventCreate(sender_str, "m.room.topic", "", content);
|
event = RoomEventCreate(sender_str, "m.room.topic", "", content);
|
||||||
JsonFree(RoomEventSend(room, event, NULL));
|
JsonFree(RoomEventSend(room, event));
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
event = RoomEventCreate(
|
event = RoomEventCreate(
|
||||||
sender_str,
|
sender_str,
|
||||||
"m.room.canonical_alias", "", content);
|
"m.room.canonical_alias", "", content);
|
||||||
JsonFree(RoomEventSend(room, event, NULL));
|
JsonFree(RoomEventSend(room, event));
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
|
|
||||||
Free(fullStr);
|
Free(fullStr);
|
||||||
|
@ -299,7 +299,7 @@ RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s)
|
||||||
}
|
}
|
||||||
|
|
||||||
event = RoomEventCreate(sender_str, "m.room.power_levels", "", pl_content);
|
event = RoomEventCreate(sender_str, "m.room.power_levels", "", pl_content);
|
||||||
JsonFree(RoomEventSend(room, event, NULL));
|
JsonFree(RoomEventSend(room, event));
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
|
|
||||||
JsonValueFree(JsonSet(
|
JsonValueFree(JsonSet(
|
||||||
|
@ -688,7 +688,7 @@ PopulateEventV1(Room * room, HashMap * event, PduV1 * pdu, ServerPart serv)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
AuthoriseCreateV1(PduV1 pdu, char **errp)
|
AuthoriseCreateV1(PduV1 pdu)
|
||||||
{
|
{
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
CommonID sender = { 0 }, room_id = { 0 };
|
CommonID sender = { 0 }, room_id = { 0 };
|
||||||
|
@ -696,20 +696,12 @@ AuthoriseCreateV1(PduV1 pdu, char **errp)
|
||||||
|
|
||||||
if (ArraySize(pdu.auth_events) > 0)
|
if (ArraySize(pdu.auth_events) > 0)
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Room creation event has auth events";
|
|
||||||
}
|
|
||||||
ret = false;
|
ret = false;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
if (!ParseCommonID(pdu.room_id, &room_id) ||
|
if (!ParseCommonID(pdu.room_id, &room_id) ||
|
||||||
!ParseCommonID(pdu.sender, &sender))
|
!ParseCommonID(pdu.sender, &sender))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Couldn't parse the sender/room ID";
|
|
||||||
}
|
|
||||||
ret = false;
|
ret = false;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -717,20 +709,12 @@ AuthoriseCreateV1(PduV1 pdu, char **errp)
|
||||||
id_serv = ParserRecomposeServerPart(room_id.server);
|
id_serv = ParserRecomposeServerPart(room_id.server);
|
||||||
if (!StrEquals(sender_serv, id_serv))
|
if (!StrEquals(sender_serv, id_serv))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Room is not properly namespaced";
|
|
||||||
}
|
|
||||||
ret = false;
|
ret = false;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
/* TODO: Check room_version as in step 1.3 */
|
/* TODO: Check room_version as in step 1.3 */
|
||||||
if (!HashMapGet(pdu.content, "creator"))
|
if (!HashMapGet(pdu.content, "creator"))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Room creation event has auth events";
|
|
||||||
}
|
|
||||||
ret = false;
|
ret = false;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
@ -772,10 +756,7 @@ ValidAuthEventV1(PduV1 *auth_pdu, PduV1 *pdu)
|
||||||
JsonValue *third_pid =
|
JsonValue *third_pid =
|
||||||
JsonGet(pdu->content, 1, "third_party_invite");
|
JsonGet(pdu->content, 1, "third_party_invite");
|
||||||
|
|
||||||
/* The PDU's state_key is the target. So we check if if the
|
if (IsState(auth_pdu, "m.room.member", auth_pdu->sender))
|
||||||
* auth PDU would count as the target's membership. Was very fun to
|
|
||||||
* find that out when I wanted to kick my 'yukari' alt. */
|
|
||||||
if (IsState(auth_pdu, "m.room.member", pdu->state_key))
|
|
||||||
{
|
{
|
||||||
/* TODO: Check if it's the latest in terms of [pdu] */
|
/* TODO: Check if it's the latest in terms of [pdu] */
|
||||||
return true;
|
return true;
|
||||||
|
@ -807,8 +788,6 @@ ValidAuthEventV1(PduV1 *auth_pdu, PduV1 *pdu)
|
||||||
static bool
|
static bool
|
||||||
VerifyPDUV1(PduV1 *auth_pdu)
|
VerifyPDUV1(PduV1 *auth_pdu)
|
||||||
{
|
{
|
||||||
/* TODO: The PDU could come from an unknown source, which may lack
|
|
||||||
* the tools to verify softfailing(or a source that we may not trust)*/
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
* https://spec.matrix.org/v1.7/server-server-api/
|
* https://spec.matrix.org/v1.7/server-server-api/
|
||||||
* #checks-performed-on-receipt-of-a-pdu */
|
* #checks-performed-on-receipt-of-a-pdu */
|
||||||
|
@ -825,7 +804,7 @@ VerifyPDUV1(PduV1 *auth_pdu)
|
||||||
* soft-failed */
|
* soft-failed */
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
ConsiderAuthEventsV1(Room * room, PduV1 pdu, char **errp)
|
ConsiderAuthEventsV1(Room * room, PduV1 pdu)
|
||||||
{
|
{
|
||||||
char *ignored;
|
char *ignored;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@ -844,10 +823,6 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu, char **errp)
|
||||||
{
|
{
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
HashMapFree(state_keytype);
|
HashMapFree(state_keytype);
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Couldn't parse an auth event";
|
|
||||||
}
|
|
||||||
return false; /* Yeah... we aren't doing that. */
|
return false; /* Yeah... we aren't doing that. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -859,11 +834,6 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu, char **errp)
|
||||||
if (HashMapGet(state_keytype, key_type_id))
|
if (HashMapGet(state_keytype, key_type_id))
|
||||||
{
|
{
|
||||||
/* Duplicate found! We actually ignore it's actual value. */
|
/* Duplicate found! We actually ignore it's actual value. */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Duplicate auth event was found";
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
PduV1Free(&auth_pdu);
|
PduV1Free(&auth_pdu);
|
||||||
|
|
||||||
|
@ -881,10 +851,6 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu, char **errp)
|
||||||
* described in the server specification, reject. */
|
* described in the server specification, reject. */
|
||||||
if (!ValidAuthEventV1(&auth_pdu, &pdu))
|
if (!ValidAuthEventV1(&auth_pdu, &pdu))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Invalid authevent given.";
|
|
||||||
}
|
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
PduV1Free(&auth_pdu);
|
PduV1Free(&auth_pdu);
|
||||||
HashMapFree(state_keytype);
|
HashMapFree(state_keytype);
|
||||||
|
@ -895,10 +861,6 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu, char **errp)
|
||||||
* TODO */
|
* TODO */
|
||||||
if (!VerifyPDUV1(&auth_pdu))
|
if (!VerifyPDUV1(&auth_pdu))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Event depends on rejected PDUs";
|
|
||||||
}
|
|
||||||
PduV1Free(&auth_pdu);
|
PduV1Free(&auth_pdu);
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
HashMapFree(state_keytype);
|
HashMapFree(state_keytype);
|
||||||
|
@ -916,10 +878,6 @@ ConsiderAuthEventsV1(Room * room, PduV1 pdu, char **errp)
|
||||||
PduV1Free(&auth_pdu);
|
PduV1Free(&auth_pdu);
|
||||||
}
|
}
|
||||||
HashMapFree(state_keytype);
|
HashMapFree(state_keytype);
|
||||||
if (!room_create && errp)
|
|
||||||
{
|
|
||||||
*errp = "Room creation event was not in the PDU's auth events";
|
|
||||||
}
|
|
||||||
return room_create; /* Step 2.4 is actually done here. */
|
return room_create; /* Step 2.4 is actually done here. */
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
|
@ -957,24 +915,16 @@ end:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
AuthoriseAliasV1(PduV1 pdu, char **errp)
|
AuthoriseAliasV1(PduV1 pdu)
|
||||||
{
|
{
|
||||||
/* Step 4.1: If event has no state_key, reject. */
|
/* Step 4.1: If event has no state_key, reject. */
|
||||||
if (!pdu.state_key || StrEquals(pdu.state_key, ""))
|
if (!pdu.state_key || StrEquals(pdu.state_key, ""))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 4.1 fail: no state key in the alias";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Step 4.2: If sender's domain doesn't matches state_key, reject. */
|
/* Step 4.2: If sender's domain doesn't matches state_key, reject. */
|
||||||
if (!VerifyServers(pdu.state_key, pdu.sender))
|
if (!VerifyServers(pdu.state_key, pdu.sender))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 4.2 fail: alias domain doesnt match statekey";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -982,7 +932,7 @@ AuthoriseAliasV1(PduV1 pdu, char **errp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state)
|
||||||
{
|
{
|
||||||
int64_t invite_level;
|
int64_t invite_level;
|
||||||
int64_t pdu_level;
|
int64_t pdu_level;
|
||||||
|
@ -997,20 +947,12 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
/* Step 5.3.1.1: If target user is banned, reject. */
|
/* Step 5.3.1.1: If target user is banned, reject. */
|
||||||
if (RoomUserHasMembership(room, state, pdu.state_key, "ban"))
|
if (RoomUserHasMembership(room, state, pdu.state_key, "ban"))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.1.1 fail: target is banned";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Step 5.3.1.2: If content.third_party_invite does not have a signed
|
/* Step 5.3.1.2: If content.third_party_invite does not have a signed
|
||||||
* property, reject. */
|
* property, reject. */
|
||||||
if (!(signed_val = JsonGet(third_pi_obj, 1, "signed")))
|
if (!(signed_val = JsonGet(third_pi_obj, 1, "signed")))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.1.2 fail: unsigned 3PII";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
signed_obj = JsonValueAsObject(signed_val);
|
signed_obj = JsonValueAsObject(signed_val);
|
||||||
|
@ -1019,28 +961,16 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
* reject. */
|
* reject. */
|
||||||
if (!(mxid = JsonGet(signed_obj, 1, "mxid")))
|
if (!(mxid = JsonGet(signed_obj, 1, "mxid")))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.1.3 fail: no MXID in 3PII";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!(token = JsonGet(signed_obj, 1, "token")))
|
if (!(token = JsonGet(signed_obj, 1, "token")))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.1.3 fail: no token in 3PII";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 5.3.1.4: If mxid does not match state_key, reject. */
|
/* Step 5.3.1.4: If mxid does not match state_key, reject. */
|
||||||
if (!StrEquals(JsonValueAsString(mxid), pdu.state_key))
|
if (!StrEquals(JsonValueAsString(mxid), pdu.state_key))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.1.4 fail: 3PII's MXID != state_key";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,10 +980,6 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
state,
|
state,
|
||||||
"m.room.third_party_invite", JsonValueAsString(token))))
|
"m.room.third_party_invite", JsonValueAsString(token))))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.1.5 fail: no proper 3PII event";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
third_pi_event = RoomEventFetch(room, third_pi_id);
|
third_pi_event = RoomEventFetch(room, third_pi_id);
|
||||||
|
@ -1063,10 +989,6 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
thirdpi_event_sender = JsonValueAsString(JsonGet(third_pi_event, 1, "sender"));
|
thirdpi_event_sender = JsonValueAsString(JsonGet(third_pi_event, 1, "sender"));
|
||||||
if (!StrEquals(thirdpi_event_sender, pdu.sender))
|
if (!StrEquals(thirdpi_event_sender, pdu.sender))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.1.6 fail: sender does not match 3PII";
|
|
||||||
}
|
|
||||||
JsonFree(third_pi_event);
|
JsonFree(third_pi_event);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1081,10 +1003,6 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
* - A list of public keys in the public_keys property. */
|
* - A list of public keys in the public_keys property. */
|
||||||
|
|
||||||
/* Step 5.3.1.8: Otherwise, reject. */
|
/* Step 5.3.1.8: Otherwise, reject. */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.1.8 fail: signature check do not match";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,20 +1010,12 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
* reject. */
|
* reject. */
|
||||||
if (!RoomUserHasMembership(room, state, pdu.sender, "join"))
|
if (!RoomUserHasMembership(room, state, pdu.sender, "join"))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.2 fail: sender is not 'join'ed";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Step 5.3.3: If target user's current membership state is join or ban, reject. */
|
/* Step 5.3.3: If target user’s current membership state is join or ban, reject. */
|
||||||
if (RoomUserHasMembership(room, state, pdu.state_key, "join") ||
|
if (RoomUserHasMembership(room, state, pdu.state_key, "join") ||
|
||||||
RoomUserHasMembership(room, state, pdu.state_key, "ban"))
|
RoomUserHasMembership(room, state, pdu.state_key, "ban"))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.3 fail: target is 'join'|'ban'd";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1118,14 +1028,10 @@ AuthorizeInviteMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/* Step 5.3.5: Otherwise, reject. */
|
/* Step 5.3.5: Otherwise, reject. */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.3.5 fail: sender has no permissions to do so";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
AuthorizeLeaveMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
AuthorizeLeaveMembershipV1(Room * room, PduV1 pdu, State *state)
|
||||||
{
|
{
|
||||||
int64_t ban_level = RoomMinPL(room, state, NULL, "ban");
|
int64_t ban_level = RoomMinPL(room, state, NULL, "ban");
|
||||||
int64_t kick_level = RoomMinPL(room, state, NULL, "kick");
|
int64_t kick_level = RoomMinPL(room, state, NULL, "kick");
|
||||||
|
@ -1136,26 +1042,15 @@ AuthorizeLeaveMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
* that user's current membership state is invite or join. */
|
* that user's current membership state is invite or join. */
|
||||||
if (StrEquals(pdu.sender, pdu.state_key))
|
if (StrEquals(pdu.sender, pdu.state_key))
|
||||||
{
|
{
|
||||||
bool flag =
|
return
|
||||||
RoomUserHasMembership(room, state, pdu.sender, "invite") ||
|
RoomUserHasMembership(room, state, pdu.sender, "invite") ||
|
||||||
RoomUserHasMembership(room, state, pdu.sender, "join");
|
RoomUserHasMembership(room, state, pdu.sender, "join");
|
||||||
if (!flag && errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.4.1 fail: user tries to leave but is "
|
|
||||||
"~'invite' AND ~'join'.";
|
|
||||||
}
|
|
||||||
return flag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 5.4.2: If the sender's current membership state is not join,
|
/* Step 5.4.2: If the sender's current membership state is not join,
|
||||||
* reject. */
|
* reject. */
|
||||||
if (!RoomUserHasMembership(room, state, pdu.sender, "join"))
|
if (!RoomUserHasMembership(room, state, pdu.sender, "join"))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.4.2 fail: sender tries to kick but is "
|
|
||||||
"~'invite'.";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1164,11 +1059,6 @@ AuthorizeLeaveMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
if (RoomUserHasMembership(room, state, pdu.state_key, "ban") &&
|
if (RoomUserHasMembership(room, state, pdu.state_key, "ban") &&
|
||||||
sender_level < ban_level)
|
sender_level < ban_level)
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.4.3 fail: sender tries to unban but has no "
|
|
||||||
"permissions to do so.";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1181,26 +1071,16 @@ AuthorizeLeaveMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 5.4.5: Otherwise, reject. */
|
/* Step 5.4.5: Otherwise, reject. */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.4.5 fail: sender tried to kick but has no "
|
|
||||||
"permissions to do so.";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
AuthorizeBanMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
AuthorizeBanMembershipV1(Room * room, PduV1 pdu, State *state)
|
||||||
{
|
{
|
||||||
int64_t ban_pl, pdu_pl, target_pl;
|
int64_t ban_pl, pdu_pl, target_pl;
|
||||||
|
|
||||||
/* Step 5.5.1: If the sender's current membership state is not join, reject. */
|
/* Step 5.5.1: If the sender's current membership state is not join, reject. */
|
||||||
if (!RoomUserHasMembership(room, state, pdu.sender, "join"))
|
if (!RoomUserHasMembership(room, state, pdu.sender, "join"))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.5.1 fail: sender tries to ban but is not "
|
|
||||||
"'join'ed";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1216,15 +1096,10 @@ AuthorizeBanMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 5.5.3: Otherwise, reject. */
|
/* Step 5.5.3: Otherwise, reject. */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.5.3 fail: sender tries to ban has no permissions to "
|
|
||||||
"do so";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
AuthorizeJoinMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
AuthorizeJoinMembershipV1(Room * room, PduV1 pdu, State *state)
|
||||||
{
|
{
|
||||||
/* Step 5.2.1: If the only previous event is an m.room.create and the
|
/* Step 5.2.1: If the only previous event is an m.room.create and the
|
||||||
* state_key is the creator, allow. */
|
* state_key is the creator, allow. */
|
||||||
|
@ -1257,20 +1132,11 @@ AuthorizeJoinMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
/* Step 5.2.2: If the sender does not match state_key, reject. */
|
/* Step 5.2.2: If the sender does not match state_key, reject. */
|
||||||
if (!StrEquals(pdu.sender, pdu.state_key))
|
if (!StrEquals(pdu.sender, pdu.state_key))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.2.2 fail: sender does not match statekey "
|
|
||||||
"on 'join'";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/* Step 5.2.3: If the sender is banned, reject. */
|
/* Step 5.2.3: If the sender is banned, reject. */
|
||||||
if (RoomUserHasMembership(room, state, pdu.sender, "ban"))
|
if (RoomUserHasMembership(room, state, pdu.sender, "ban"))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.2.2 fail: sender is banned on 'join'";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,16 +1153,11 @@ AuthorizeJoinMembershipV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 5.2.6: Otherwise, reject. */
|
/* Step 5.2.6: Otherwise, reject. */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.2.6 fail: join_rule does not allow 'join'";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
AuthoriseMemberV1(Room * room, PduV1 pdu, State *state, char **errp)
|
AuthoriseMemberV1(Room * room, PduV1 pdu, State *state)
|
||||||
{
|
{
|
||||||
JsonValue *membership;
|
JsonValue *membership;
|
||||||
char *membership_str;
|
char *membership_str;
|
||||||
|
@ -1306,26 +1167,18 @@ AuthoriseMemberV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
StrEquals(pdu.state_key, "") ||
|
StrEquals(pdu.state_key, "") ||
|
||||||
!(membership = JsonGet(pdu.content, 1, "membership")))
|
!(membership = JsonGet(pdu.content, 1, "membership")))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.1 fail: broken membership's statekey/membership";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (JsonValueType(membership) != JSON_STRING)
|
if (JsonValueType(membership) != JSON_STRING)
|
||||||
{
|
{
|
||||||
/* Also check for the type */
|
/* Also check for the type */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Step 5.1 fail: broken membership's membership";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
membership_str = JsonValueAsString(membership);
|
membership_str = JsonValueAsString(membership);
|
||||||
#define JumpIfMembership(mem, func) do { \
|
#define JumpIfMembership(mem, func) do { \
|
||||||
if (StrEquals(membership_str, mem)) \
|
if (StrEquals(membership_str, mem)) \
|
||||||
{ \
|
{ \
|
||||||
return func(room, pdu, state, errp); \
|
return func(room, pdu, state); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -1522,7 +1375,7 @@ AuthorisePowerLevelsV1(Room * room, PduV1 pdu, State *state)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool
|
bool
|
||||||
RoomAuthoriseEventV1(Room * room, PduV1 pdu, State *state, char **errp)
|
RoomAuthoriseEventV1(Room * room, PduV1 pdu, State *state)
|
||||||
{
|
{
|
||||||
HashMap *create_event;
|
HashMap *create_event;
|
||||||
char *create_event_id;
|
char *create_event_id;
|
||||||
|
@ -1532,11 +1385,11 @@ RoomAuthoriseEventV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
/* Step 1: If m.room.create */
|
/* Step 1: If m.room.create */
|
||||||
if (StrEquals(pdu.type, "m.room.create"))
|
if (StrEquals(pdu.type, "m.room.create"))
|
||||||
{
|
{
|
||||||
return AuthoriseCreateV1(pdu, errp);
|
return AuthoriseCreateV1(pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 2: Considering the event's auth_events. */
|
/* Step 2: Considering the event's auth_events. */
|
||||||
if (!ConsiderAuthEventsV1(room, pdu, errp))
|
if (!ConsiderAuthEventsV1(room, pdu))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1550,11 +1403,6 @@ RoomAuthoriseEventV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
if (!state || !create_event_id)
|
if (!state || !create_event_id)
|
||||||
{
|
{
|
||||||
/* At this point, [create_event_id] has to exist */
|
/* At this point, [create_event_id] has to exist */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "No creation event in the state. Needless to say, "
|
|
||||||
"your room is done for.";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
create_event = RoomEventFetch(room, create_event_id);
|
create_event = RoomEventFetch(room, create_event_id);
|
||||||
|
@ -1568,10 +1416,6 @@ RoomAuthoriseEventV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
char *p_sender = pdu.sender;
|
char *p_sender = pdu.sender;
|
||||||
if (!VerifyServers(c_sender, p_sender))
|
if (!VerifyServers(c_sender, p_sender))
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Trying to access a room with m.federate off.";
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1581,13 +1425,13 @@ RoomAuthoriseEventV1(Room * room, PduV1 pdu, State *state, char **errp)
|
||||||
/* Step 4: If type is m.room.aliases */
|
/* Step 4: If type is m.room.aliases */
|
||||||
if (StrEquals(pdu.type, "m.room.aliases"))
|
if (StrEquals(pdu.type, "m.room.aliases"))
|
||||||
{
|
{
|
||||||
return AuthoriseAliasV1(pdu, errp);
|
return AuthoriseAliasV1(pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 5: If type is m.room.member */
|
/* Step 5: If type is m.room.member */
|
||||||
if (StrEquals(pdu.type, "m.room.member"))
|
if (StrEquals(pdu.type, "m.room.member"))
|
||||||
{
|
{
|
||||||
return AuthoriseMemberV1(room, pdu, state, errp);
|
return AuthoriseMemberV1(room, pdu, state);
|
||||||
}
|
}
|
||||||
/* Step 6: If the sender's current membership state is not join, reject. */
|
/* Step 6: If the sender's current membership state is not join, reject. */
|
||||||
if (!RoomUserHasMembership(room, state, pdu.sender, "join"))
|
if (!RoomUserHasMembership(room, state, pdu.sender, "join"))
|
||||||
|
@ -1727,27 +1571,19 @@ EventFitsV1(PduV1 pdu)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static PduV1Status
|
static PduV1Status
|
||||||
RoomGetEventStatusV1(Room *room, PduV1 *pdu, State *prev, bool client, char **errp)
|
RoomGetEventStatusV1(Room *room, PduV1 *pdu, State *prev, bool client)
|
||||||
{
|
{
|
||||||
if (!room || !pdu || !prev)
|
if (!room || !pdu || !prev)
|
||||||
{
|
{
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "Illegal arguments given to RoomGetEventStatusV1";
|
|
||||||
}
|
|
||||||
return PDUV1_STATUS_DROPPED;
|
return PDUV1_STATUS_DROPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EventFitsV1(*pdu))
|
if (!EventFitsV1(*pdu))
|
||||||
{
|
{
|
||||||
/* Reject this event as it is too large. */
|
/* Reject this event as it is too large. */
|
||||||
if (errp)
|
|
||||||
{
|
|
||||||
*errp = "PDU is too large to fit";
|
|
||||||
}
|
|
||||||
return PDUV1_STATUS_DROPPED;
|
return PDUV1_STATUS_DROPPED;
|
||||||
}
|
}
|
||||||
if (!RoomAuthoriseEventV1(room, *pdu, prev, errp))
|
if (!RoomAuthoriseEventV1(room, *pdu, prev))
|
||||||
{
|
{
|
||||||
/* Reject this event as the current state does not allow it.
|
/* Reject this event as the current state does not allow it.
|
||||||
* TODO: Make the auth check function return a string showing the
|
* TODO: Make the auth check function return a string showing the
|
||||||
|
@ -1759,7 +1595,7 @@ RoomGetEventStatusV1(Room *room, PduV1 *pdu, State *prev, bool client, char **er
|
||||||
{
|
{
|
||||||
State *current = StateCurrent(room);
|
State *current = StateCurrent(room);
|
||||||
|
|
||||||
if (!RoomAuthoriseEventV1(room, *pdu, current, NULL))
|
if (!RoomAuthoriseEventV1(room, *pdu, current))
|
||||||
{
|
{
|
||||||
StateFree(current);
|
StateFree(current);
|
||||||
return PDUV1_STATUS_SOFTFAIL;
|
return PDUV1_STATUS_SOFTFAIL;
|
||||||
|
@ -1770,7 +1606,7 @@ RoomGetEventStatusV1(Room *room, PduV1 *pdu, State *prev, bool client, char **er
|
||||||
return PDUV1_STATUS_ACCEPTED;
|
return PDUV1_STATUS_ACCEPTED;
|
||||||
}
|
}
|
||||||
static HashMap *
|
static HashMap *
|
||||||
RoomEventSendV1(Room * room, HashMap * event, char **errp)
|
RoomEventSendV1(Room * room, HashMap * event)
|
||||||
{
|
{
|
||||||
PduV1 pdu = { 0 };
|
PduV1 pdu = { 0 };
|
||||||
HashMap *pdu_object = NULL;
|
HashMap *pdu_object = NULL;
|
||||||
|
@ -1866,7 +1702,8 @@ RoomEventSendV1(Room * room, HashMap * event, char **errp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO: For PDU events, we should verify their hashes. */
|
/* TODO: For PDU events, we should verify their hashes. */
|
||||||
status = RoomGetEventStatusV1(room, &pdu, state, client_event, errp);
|
status = RoomGetEventStatusV1(room, &pdu, state, client_event);
|
||||||
|
Log(LOG_DEBUG, "status='%s'", PduV1StatusToStr(status));
|
||||||
if (status == PDUV1_STATUS_DROPPED)
|
if (status == PDUV1_STATUS_DROPPED)
|
||||||
{
|
{
|
||||||
goto finish;
|
goto finish;
|
||||||
|
@ -1908,7 +1745,7 @@ RoomEventSendV3(Room * room, HashMap * event)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
HashMap *
|
HashMap *
|
||||||
RoomEventSend(Room * room, HashMap * event, char **errp)
|
RoomEventSend(Room * room, HashMap * event)
|
||||||
{
|
{
|
||||||
if (!room || !event)
|
if (!room || !event)
|
||||||
{
|
{
|
||||||
|
@ -1917,7 +1754,7 @@ RoomEventSend(Room * room, HashMap * event, char **errp)
|
||||||
if (room->version < 3)
|
if (room->version < 3)
|
||||||
{
|
{
|
||||||
/* Manage with PDUv1 */
|
/* Manage with PDUv1 */
|
||||||
return RoomEventSendV1(room, event, errp);
|
return RoomEventSendV1(room, event);
|
||||||
}
|
}
|
||||||
/* Manage with PDUv3 otherwise */
|
/* Manage with PDUv3 otherwise */
|
||||||
return RoomEventSendV3(room, event);
|
return RoomEventSendV3(room, event);
|
||||||
|
@ -2361,7 +2198,7 @@ RoomSendInvite(User *sender, bool direct, char *user, Room *room)
|
||||||
JsonSet(content, JsonValueBoolean(direct), 1, "is_direct");
|
JsonSet(content, JsonValueBoolean(direct), 1, "is_direct");
|
||||||
JsonSet(content, JsonValueString("invite"), 1, "membership");
|
JsonSet(content, JsonValueString("invite"), 1, "membership");
|
||||||
event = RoomEventCreate(senderStr, "m.room.member", user, content);
|
event = RoomEventCreate(senderStr, "m.room.member", user, content);
|
||||||
JsonFree(RoomEventSend(room, event, NULL));
|
JsonFree(RoomEventSend(room, event));
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
|
|
||||||
/* TODO: Send to "local" invite list if user is local. */
|
/* TODO: Send to "local" invite list if user is local. */
|
||||||
|
@ -2466,55 +2303,7 @@ end:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
RoomLeave(Room *room, User *user, char **errp)
|
RoomJoin(Room *room, User *user)
|
||||||
{
|
|
||||||
CommonID *userId = NULL;
|
|
||||||
char *userString = NULL;
|
|
||||||
char *server = NULL;
|
|
||||||
HashMap *content = NULL;
|
|
||||||
HashMap *event = NULL;
|
|
||||||
HashMap *pdu = NULL;
|
|
||||||
bool ret = false;
|
|
||||||
|
|
||||||
if (!room || !user)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
server = ConfigGetServerName(room->db);
|
|
||||||
if (!server)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
userId = UserIdParse(UserGetName(user), server);
|
|
||||||
userId->sigil = '@';
|
|
||||||
userString = ParserRecomposeCommonID(*userId);
|
|
||||||
Free(server);
|
|
||||||
server = NULL;
|
|
||||||
|
|
||||||
content = HashMapCreate();
|
|
||||||
JsonSet(content, JsonValueString("leave"), 1, "membership");
|
|
||||||
event = RoomEventCreate(userString, "m.room.member", userString, content);
|
|
||||||
pdu = RoomEventSend(room, event, errp);
|
|
||||||
|
|
||||||
/* TODO: One ought to be extremely careful with managing users in those
|
|
||||||
* scenarios, as the DB flushes do not sync. */
|
|
||||||
ret = !!pdu;
|
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
UserRemoveJoin(user, room->id);
|
|
||||||
}
|
|
||||||
UserIdFree(userId);
|
|
||||||
JsonFree(event);
|
|
||||||
JsonFree(pdu);
|
|
||||||
if (userString)
|
|
||||||
{
|
|
||||||
Free(userString);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
bool
|
|
||||||
RoomJoin(Room *room, User *user, char **errp)
|
|
||||||
{
|
{
|
||||||
CommonID *userId = NULL;
|
CommonID *userId = NULL;
|
||||||
char *userString = NULL;
|
char *userString = NULL;
|
||||||
|
@ -2549,15 +2338,9 @@ RoomJoin(Room *room, User *user, char **errp)
|
||||||
content = HashMapCreate();
|
content = HashMapCreate();
|
||||||
JsonSet(content, JsonValueString("join"), 1, "membership");
|
JsonSet(content, JsonValueString("join"), 1, "membership");
|
||||||
event = RoomEventCreate(userString, "m.room.member", userString, content);
|
event = RoomEventCreate(userString, "m.room.member", userString, content);
|
||||||
pdu = RoomEventSend(room, event, errp);
|
pdu = RoomEventSend(room, event);
|
||||||
|
|
||||||
/* TODO: One ought to be extremely careful with managing users in those
|
|
||||||
* scenarios, as the DB flushes do not sync. */
|
|
||||||
ret = !!pdu;
|
ret = !!pdu;
|
||||||
if (ret)
|
|
||||||
{
|
|
||||||
UserAddJoin(user, room->id);
|
|
||||||
}
|
|
||||||
end:
|
end:
|
||||||
UserIdFree(userId);
|
UserIdFree(userId);
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
|
|
|
@ -82,7 +82,7 @@ RouterBuild(void)
|
||||||
R("/_matrix/client/v3/rooms/(.*)/state/(.*)", RouteSendState);
|
R("/_matrix/client/v3/rooms/(.*)/state/(.*)", RouteSendState);
|
||||||
R("/_matrix/client/v3/rooms/(.*)/event/(.*)", RouteFetchEvent);
|
R("/_matrix/client/v3/rooms/(.*)/event/(.*)", RouteFetchEvent);
|
||||||
R("/_matrix/client/v3/rooms/(.*)/(join|leave)", RouteJoinRoom);
|
R("/_matrix/client/v3/rooms/(.*)/(join|leave)", RouteJoinRoom);
|
||||||
R("/_matrix/client/v3/rooms/(.*)/(kick|ban|unban)", RouteKickRoom);
|
R("/_matrix/client/v3/rooms/(.*)/(kick|ban)", RouteKickRoom);
|
||||||
R("/_matrix/client/v3/rooms/(.*)/messages", RouteMessages);
|
R("/_matrix/client/v3/rooms/(.*)/messages", RouteMessages);
|
||||||
|
|
||||||
R("/_matrix/client/v3/join/(.*)", RouteJoinRoomAlias);
|
R("/_matrix/client/v3/join/(.*)", RouteJoinRoomAlias);
|
||||||
|
|
|
@ -130,10 +130,11 @@ ROUTE_IMPL(RouteJoinRoom, path, argp)
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
/* TODO: Custom reason parameter. */
|
/* TODO: Custom reason parameter. */
|
||||||
if (!RoomJoin(room, user, &err))
|
if (!RoomJoin(room, user))
|
||||||
{
|
{
|
||||||
HttpResponseStatus(args->context, HTTP_UNAUTHORIZED);
|
err = "User could not be the room due to unknown reasons.";
|
||||||
response = MatrixErrorCreate(M_BAD_STATE, err);
|
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
response = MatrixErrorCreate(M_UNKNOWN, err);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +143,9 @@ ROUTE_IMPL(RouteJoinRoom, path, argp)
|
||||||
}
|
}
|
||||||
else if (StrEquals(action, "leave"))
|
else if (StrEquals(action, "leave"))
|
||||||
{
|
{
|
||||||
|
HashMap *membership, *content;
|
||||||
|
HashMap *pduResponse;
|
||||||
|
|
||||||
if (!RoomContainsUser(room, sender))
|
if (!RoomContainsUser(room, sender))
|
||||||
{
|
{
|
||||||
err = "User is not already in the room.";
|
err = "User is not already in the room.";
|
||||||
|
@ -151,12 +155,25 @@ ROUTE_IMPL(RouteJoinRoom, path, argp)
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RoomLeave(room, user, &err))
|
content = HashMapCreate();
|
||||||
|
membership = RoomEventCreate(
|
||||||
|
sender, "m.room.member", sender,
|
||||||
|
content
|
||||||
|
);
|
||||||
|
|
||||||
|
HashMapSet(content, "membership", JsonValueString("leave"));
|
||||||
|
pduResponse = RoomEventSend(room, membership);
|
||||||
|
if (!pduResponse)
|
||||||
{
|
{
|
||||||
HttpResponseStatus(args->context, HTTP_UNAUTHORIZED);
|
err = "Couldn't accept leave event";
|
||||||
response = MatrixErrorCreate(M_BAD_STATE, err);
|
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
response = MatrixErrorCreate(M_UNKNOWN, err);
|
||||||
|
|
||||||
|
JsonFree(membership);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
JsonFree(pduResponse);
|
||||||
|
JsonFree(membership);
|
||||||
|
|
||||||
response = HashMapCreate();
|
response = HashMapCreate();
|
||||||
}
|
}
|
||||||
|
@ -196,7 +213,8 @@ ROUTE_IMPL(RouteKickRoom, path, argp)
|
||||||
char *action = ArrayGet(path, 1);
|
char *action = ArrayGet(path, 1);
|
||||||
char *kicked = NULL, *reason = NULL;
|
char *kicked = NULL, *reason = NULL;
|
||||||
char *sender = NULL, *serverName = NULL;
|
char *sender = NULL, *serverName = NULL;
|
||||||
char *membershipState;
|
char *membershipState = StrEquals(action, "kick") ?
|
||||||
|
"leave" : "ban";
|
||||||
|
|
||||||
Room *room = NULL;
|
Room *room = NULL;
|
||||||
|
|
||||||
|
@ -208,26 +226,6 @@ ROUTE_IMPL(RouteKickRoom, path, argp)
|
||||||
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
||||||
return MatrixErrorCreate(M_UNKNOWN, NULL);
|
return MatrixErrorCreate(M_UNKNOWN, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StrEquals(action, "kick"))
|
|
||||||
{
|
|
||||||
membershipState = "leave";
|
|
||||||
}
|
|
||||||
else if (StrEquals(action, "ban"))
|
|
||||||
{
|
|
||||||
membershipState = "ban";
|
|
||||||
}
|
|
||||||
else if (StrEquals(action, "unban"))
|
|
||||||
{
|
|
||||||
membershipState = "leave";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Should be impossible */
|
|
||||||
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
|
||||||
return MatrixErrorCreate(M_UNKNOWN, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HttpRequestMethodGet(args->context) != HTTP_POST)
|
if (HttpRequestMethodGet(args->context) != HTTP_POST)
|
||||||
{
|
{
|
||||||
err = "Unknown request method.";
|
err = "Unknown request method.";
|
||||||
|
@ -286,7 +284,7 @@ ROUTE_IMPL(RouteKickRoom, path, argp)
|
||||||
response = MatrixErrorCreate(M_FORBIDDEN, err);
|
response = MatrixErrorCreate(M_FORBIDDEN, err);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
if (RoomContainsUser(room, kicked) == StrEquals(action, "unban"))
|
if (!RoomContainsUser(room, kicked))
|
||||||
{
|
{
|
||||||
err = "Victim is not present in the room";
|
err = "Victim is not present in the room";
|
||||||
HttpResponseStatus(args->context, HTTP_BAD_REQUEST);
|
HttpResponseStatus(args->context, HTTP_BAD_REQUEST);
|
||||||
|
@ -307,11 +305,12 @@ ROUTE_IMPL(RouteKickRoom, path, argp)
|
||||||
HashMapSet(content, "reason", JsonValueString(reason));
|
HashMapSet(content, "reason", JsonValueString(reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
pduResponse = RoomEventSend(room, membership, &err);
|
pduResponse = RoomEventSend(room, membership);
|
||||||
if (!pduResponse)
|
if (!pduResponse)
|
||||||
{
|
{
|
||||||
HttpResponseStatus(args->context, HTTP_UNAUTHORIZED);
|
err = "Couldn't accept event";
|
||||||
response = MatrixErrorCreate(M_BAD_STATE, err);
|
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
response = MatrixErrorCreate(M_UNKNOWN, err);
|
||||||
|
|
||||||
JsonFree(membership);
|
JsonFree(membership);
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
|
@ -143,10 +143,11 @@ ROUTE_IMPL(RouteJoinRoomAlias, path, argp)
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
/* TODO: Custom reason parameter. */
|
/* TODO: Custom reason parameter. */
|
||||||
if (!RoomJoin(room, user, &err))
|
if (!RoomJoin(room, user))
|
||||||
{
|
{
|
||||||
HttpResponseStatus(args->context, HTTP_UNAUTHORIZED);
|
err = "User could not be the room due to unknown reasons.";
|
||||||
response = MatrixErrorCreate(M_FORBIDDEN, err);
|
HttpResponseStatus(args->context, HTTP_INTERNAL_SERVER_ERROR);
|
||||||
|
response = MatrixErrorCreate(M_UNKNOWN, err);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ ROUTE_IMPL(RouteSendEvent, path, argp)
|
||||||
|
|
||||||
Room *room = NULL;
|
Room *room = NULL;
|
||||||
|
|
||||||
char *err = NULL;
|
char *err;
|
||||||
|
|
||||||
if (!roomId || !eventType || !transId)
|
if (!roomId || !eventType || !transId)
|
||||||
{
|
{
|
||||||
|
@ -123,11 +123,12 @@ ROUTE_IMPL(RouteSendEvent, path, argp)
|
||||||
}
|
}
|
||||||
|
|
||||||
event = RoomEventCreate(sender, eventType, NULL, JsonDuplicate(request));
|
event = RoomEventCreate(sender, eventType, NULL, JsonDuplicate(request));
|
||||||
filled = RoomEventSend(room, event, &err);
|
filled = RoomEventSend(room, event);
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
|
|
||||||
if (!filled)
|
if (!filled)
|
||||||
{
|
{
|
||||||
|
err = "User is not allowed to send event.";
|
||||||
HttpResponseStatus(args->context, HTTP_UNAUTHORIZED);
|
HttpResponseStatus(args->context, HTTP_UNAUTHORIZED);
|
||||||
response = MatrixErrorCreate(M_FORBIDDEN, err);
|
response = MatrixErrorCreate(M_FORBIDDEN, err);
|
||||||
goto finish;
|
goto finish;
|
||||||
|
@ -237,11 +238,12 @@ ROUTE_IMPL(RouteSendState, path, argp)
|
||||||
eventType, stateKey ? stateKey : "",
|
eventType, stateKey ? stateKey : "",
|
||||||
JsonDuplicate(request)
|
JsonDuplicate(request)
|
||||||
);
|
);
|
||||||
filled = RoomEventSend(room, event, &err);
|
filled = RoomEventSend(room, event);
|
||||||
JsonFree(event);
|
JsonFree(event);
|
||||||
|
|
||||||
if (!filled)
|
if (!filled)
|
||||||
{
|
{
|
||||||
|
err = "User is not allowed to send state.";
|
||||||
HttpResponseStatus(args->context, HTTP_UNAUTHORIZED);
|
HttpResponseStatus(args->context, HTTP_UNAUTHORIZED);
|
||||||
response = MatrixErrorCreate(M_FORBIDDEN, err);
|
response = MatrixErrorCreate(M_FORBIDDEN, err);
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
|
@ -63,7 +63,7 @@ SendMembership(Db *db, User *user)
|
||||||
HashMapSet(content, "displayname", JsonValueString(displayname));
|
HashMapSet(content, "displayname", JsonValueString(displayname));
|
||||||
HashMapSet(content, "avatar_url", JsonValueString(avatar_url));
|
HashMapSet(content, "avatar_url", JsonValueString(avatar_url));
|
||||||
|
|
||||||
JsonFree(RoomEventSend(room, membership, NULL));
|
JsonFree(RoomEventSend(room, membership));
|
||||||
JsonFree(membership);
|
JsonFree(membership);
|
||||||
|
|
||||||
RoomUnlock(room);
|
RoomUnlock(room);
|
||||||
|
|
|
@ -209,7 +209,7 @@ FixoutConflictV1(char *t, Room *room, State *R, HashMap *conflicts)
|
||||||
char *msg;
|
char *msg;
|
||||||
|
|
||||||
PduV1FromJson(event, &pdu, &msg);
|
PduV1FromJson(event, &pdu, &msg);
|
||||||
if (RoomAuthoriseEventV1(room, pdu, R, NULL))
|
if (RoomAuthoriseEventV1(room, pdu, R))
|
||||||
{
|
{
|
||||||
StateSet(R, pdu.type, pdu.state_key, pdu.event_id);
|
StateSet(R, pdu.type, pdu.state_key, pdu.event_id);
|
||||||
}
|
}
|
||||||
|
@ -289,7 +289,7 @@ StateResolveV1(Room * room, Array * states)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RoomAuthoriseEventV1(room, pdu, R, NULL))
|
if (RoomAuthoriseEventV1(room, pdu, R))
|
||||||
{
|
{
|
||||||
StateSet(R, pdu.type, pdu.state_key, pdu.event_id);
|
StateSet(R, pdu.type, pdu.state_key, pdu.event_id);
|
||||||
PduV1Free(&pdu);
|
PduV1Free(&pdu);
|
||||||
|
|
71
src/User.c
71
src/User.c
|
@ -130,8 +130,9 @@ UserLock(Db * db, char *name)
|
||||||
user->name = StrDuplicate(name);
|
user->name = StrDuplicate(name);
|
||||||
user->deviceId = NULL;
|
user->deviceId = NULL;
|
||||||
|
|
||||||
user->inviteRef = NULL;
|
user->inviteRef = DbLock(db, 3, "users", user->name, "invites");
|
||||||
user->joinRef = NULL;
|
user->joinRef = DbLock(db, 3, "users", user->name, "joins");
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +184,7 @@ UserAuthenticate(Db * db, char *accessToken)
|
||||||
bool
|
bool
|
||||||
UserUnlock(User * user)
|
UserUnlock(User * user)
|
||||||
{
|
{
|
||||||
bool refOk, joinOk, inviteOk;
|
bool ret;
|
||||||
Db *db;
|
Db *db;
|
||||||
DbRef *ref;
|
DbRef *ref;
|
||||||
|
|
||||||
|
@ -197,15 +198,14 @@ UserUnlock(User * user)
|
||||||
Free(user->name);
|
Free(user->name);
|
||||||
Free(user->deviceId);
|
Free(user->deviceId);
|
||||||
|
|
||||||
refOk = DbUnlock(db, ref);
|
ret = DbUnlock(db, ref) &&
|
||||||
joinOk = DbUnlock(db, user->joinRef);
|
DbUnlock(db, user->joinRef) &&
|
||||||
inviteOk = DbUnlock(db, user->inviteRef);
|
DbUnlock(db, user->inviteRef);
|
||||||
|
|
||||||
user->db = NULL;
|
user->db = NULL;
|
||||||
user->ref = NULL;
|
user->ref = NULL;
|
||||||
Free(user);
|
Free(user);
|
||||||
|
|
||||||
return refOk && joinOk && inviteOk;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
User *
|
User *
|
||||||
|
@ -1033,7 +1033,6 @@ void
|
||||||
UserAddInvite(User *user, char *roomId)
|
UserAddInvite(User *user, char *roomId)
|
||||||
{
|
{
|
||||||
HashMap *data;
|
HashMap *data;
|
||||||
Db *db = user ? user->db : NULL;
|
|
||||||
if (!user || !roomId)
|
if (!user || !roomId)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1041,10 +1040,9 @@ UserAddInvite(User *user, char *roomId)
|
||||||
|
|
||||||
if (!user->inviteRef)
|
if (!user->inviteRef)
|
||||||
{
|
{
|
||||||
if (!(user->inviteRef = DbLock(db, 3, "users", user->name, "invites")))
|
user->inviteRef = DbCreate(user->db,
|
||||||
{
|
3, "users", user->name, "invites"
|
||||||
user->inviteRef = DbCreate(db, 3, "users", user->name, "invites");
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data = DbJson(user->inviteRef);
|
data = DbJson(user->inviteRef);
|
||||||
|
@ -1056,19 +1054,11 @@ void
|
||||||
UserRemoveInvite(User *user, char *roomId)
|
UserRemoveInvite(User *user, char *roomId)
|
||||||
{
|
{
|
||||||
HashMap *data;
|
HashMap *data;
|
||||||
Db *db = user ? user->db : NULL;
|
|
||||||
if (!user || !roomId)
|
if (!user || !roomId)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user->inviteRef)
|
|
||||||
{
|
|
||||||
if (!(user->inviteRef = DbLock(db, 3, "users", user->name, "invites")))
|
|
||||||
{
|
|
||||||
user->inviteRef = DbCreate(db, 3, "users", user->name, "invites");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data = DbJson(user->inviteRef);
|
data = DbJson(user->inviteRef);
|
||||||
|
|
||||||
JsonValueFree(HashMapDelete(data, roomId));
|
JsonValueFree(HashMapDelete(data, roomId));
|
||||||
|
@ -1078,7 +1068,6 @@ UserListInvites(User *user)
|
||||||
{
|
{
|
||||||
Array *arr;
|
Array *arr;
|
||||||
HashMap *data;
|
HashMap *data;
|
||||||
Db *db = user ? user->db : NULL;
|
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
if (!user)
|
if (!user)
|
||||||
|
@ -1086,13 +1075,6 @@ UserListInvites(User *user)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user->inviteRef)
|
|
||||||
{
|
|
||||||
if (!(user->inviteRef = DbLock(db, 3, "users", user->name, "invites")))
|
|
||||||
{
|
|
||||||
user->inviteRef = DbCreate(db, 3, "users", user->name, "invites");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data = DbJson(user->inviteRef);
|
data = DbJson(user->inviteRef);
|
||||||
arr = HashMapKeys(data);
|
arr = HashMapKeys(data);
|
||||||
for (i = 0; i < ArraySize(arr); i++)
|
for (i = 0; i < ArraySize(arr); i++)
|
||||||
|
@ -1107,7 +1089,6 @@ void
|
||||||
UserAddJoin(User *user, char *roomId)
|
UserAddJoin(User *user, char *roomId)
|
||||||
{
|
{
|
||||||
HashMap *data;
|
HashMap *data;
|
||||||
Db *db = user ? user->db : NULL;
|
|
||||||
if (!user || !roomId)
|
if (!user || !roomId)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -1115,15 +1096,15 @@ UserAddJoin(User *user, char *roomId)
|
||||||
|
|
||||||
if (!user->joinRef)
|
if (!user->joinRef)
|
||||||
{
|
{
|
||||||
if (!(user->joinRef = DbLock(db, 3, "users", user->name, "joins")))
|
user->joinRef = DbCreate(user->db, 3, "users", user->name, "joins");
|
||||||
{
|
|
||||||
user->joinRef = DbCreate(db, 3, "users", user->name, "joins");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data = DbJson(user->joinRef);
|
data = DbJson(user->joinRef);
|
||||||
|
|
||||||
JsonValueFree(HashMapSet(data, roomId, JsonValueObject(HashMapCreate())));
|
if (data && !HashMapGet(data, roomId))
|
||||||
|
{
|
||||||
|
JsonValueFree(HashMapSet(data, roomId, JsonValueNull()));
|
||||||
|
}
|
||||||
UserNotifyUser(user);
|
UserNotifyUser(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1131,20 +1112,11 @@ void
|
||||||
UserRemoveJoin(User *user, char *roomId)
|
UserRemoveJoin(User *user, char *roomId)
|
||||||
{
|
{
|
||||||
HashMap *data;
|
HashMap *data;
|
||||||
Db *db = user ? user->db : NULL;
|
if (!user || !roomId)
|
||||||
if (!user || !roomId || !user->joinRef)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user->joinRef)
|
|
||||||
{
|
|
||||||
if (!(user->joinRef = DbLock(db, 3, "users", user->name, "joins")))
|
|
||||||
{
|
|
||||||
user->joinRef = DbCreate(db, 3, "users", user->name, "joins");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data = DbJson(user->joinRef);
|
data = DbJson(user->joinRef);
|
||||||
|
|
||||||
JsonValueFree(HashMapDelete(data, roomId));
|
JsonValueFree(HashMapDelete(data, roomId));
|
||||||
|
@ -1155,21 +1127,12 @@ UserListJoins(User *user)
|
||||||
{
|
{
|
||||||
Array *arr;
|
Array *arr;
|
||||||
HashMap *data;
|
HashMap *data;
|
||||||
Db *db = user ? user->db : NULL;
|
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
if (!user)
|
if (!user)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!user->joinRef)
|
|
||||||
{
|
|
||||||
if (!(user->joinRef = DbLock(db, 3, "users", user->name, "joins")))
|
|
||||||
{
|
|
||||||
user->joinRef = DbCreate(db, 3, "users", user->name, "joins");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data = DbJson(user->joinRef);
|
data = DbJson(user->joinRef);
|
||||||
arr = HashMapKeys(data);
|
arr = HashMapKeys(data);
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ extern int RoomPrevEventsSet(Room *, Array *);
|
||||||
* the room version, which includes setting the
|
* the room version, which includes setting the
|
||||||
* prev_events and auth_events fields correctly.
|
* prev_events and auth_events fields correctly.
|
||||||
*/
|
*/
|
||||||
extern HashMap * RoomEventSend(Room *, HashMap *, char **);
|
extern HashMap * RoomEventSend(Room *, HashMap *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends an invite to a user in a room, and tries
|
* Sends an invite to a user in a room, and tries
|
||||||
|
@ -170,7 +170,7 @@ extern HashMap * RoomEventClientify(HashMap *);
|
||||||
* Verifies whenever an event(as a PDUv1) is
|
* Verifies whenever an event(as a PDUv1) is
|
||||||
* authorised by a room.
|
* authorised by a room.
|
||||||
*/
|
*/
|
||||||
extern bool RoomAuthoriseEventV1(Room *, PduV1, State *, char **);
|
extern bool RoomAuthoriseEventV1(Room *, PduV1, State *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the room's creator as a ServerPart. This value should
|
* Gets the room's creator as a ServerPart. This value should
|
||||||
|
@ -229,13 +229,7 @@ extern bool RoomCanJoin(Room *, char *);
|
||||||
* Makes a local user join a room, and returns true if
|
* Makes a local user join a room, and returns true if
|
||||||
* the room was joined.
|
* the room was joined.
|
||||||
*/
|
*/
|
||||||
extern bool RoomJoin(Room *, User *, char **);
|
extern bool RoomJoin(Room *, User *);
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes a local user leave a room, and returns true if
|
|
||||||
* the room was left.
|
|
||||||
*/
|
|
||||||
extern bool RoomLeave(Room *, User *, char **);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds or overwrites a room alias.
|
* Adds or overwrites a room alias.
|
||||||
|
|
Loading…
Reference in a new issue