Compare commits

..

No commits in common. "a77be8b43730a1a871024212dfcf3ffa86b6249c" and "19359045e94badf6992f6ab83ca3fbdeb5797ec6" have entirely different histories.

12 changed files with 106 additions and 370 deletions

11
configure vendored
View file

@ -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}

View file

@ -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\">"

View file

@ -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);
} }

View file

@ -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 users 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);

View file

@ -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);

View file

@ -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;

View file

@ -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;
} }

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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,22 +1112,13 @@ 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));
UserNotifyUser(user); UserNotifyUser(user);
} }
@ -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);

View file

@ -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.