diff --git a/src/Room.c b/src/Room.c index a00804f..9ce15c6 100644 --- a/src/Room.c +++ b/src/Room.c @@ -2034,3 +2034,21 @@ RoomGetDB(Room *room) } return room->db; } +bool +RoomContainsUser(Room *room, char *user) +{ + HashMap *state; + bool ret; + if (!room || !user) + { + return false; + } + + state = StateCurrent(room); + + ret = RoomUserHasMembership(room, state, user, "join"); + + StateFree(state); + + return ret; +} diff --git a/src/Routes.c b/src/Routes.c index 2562e78..5059df3 100644 --- a/src/Routes.c +++ b/src/Routes.c @@ -91,6 +91,63 @@ RouterBuild(void) R("/_telodendria/admin/v1/tokens/(.*)", RouteAdminTokens); R("/_telodendria/admin/v1/tokens", RouteAdminTokens); + R("/_matrix/client/r0/capabilities", RouteCapabilities); + R("/_matrix/client/r0/login", RouteLogin); + R("/_matrix/client/r0/logout", RouteLogout); + R("/_matrix/client/r0/logout/(all)", RouteLogout); + R("/_matrix/client/r0/register", RouteRegister); + R("/_matrix/client/r0/register/(available)", RouteRegister); + R("/_matrix/client/r0/refresh", RouteRefresh); + + R("/_matrix/client/r0/account/whoami", RouteWhoami); + R("/_matrix/client/r0/account/password", RouteChangePwd); + R("/_matrix/client/r0/account/deactivate", RouteDeactivate); + + R("/_matrix/client/v1/register/m.login.registration_token/validity", RouteTokenValid); + + R("/_matrix/client/r0/account/password/(email|msisdn)/requestToken", RouteRequestToken); + R("/_matrix/client/r0/register/(email|msisdn)/requestToken", RouteRequestToken); + + R("/_matrix/client/r0/profile/(.*)", RouteUserProfile); + R("/_matrix/client/r0/profile/(.*)/(avatar_url|displayname)", RouteUserProfile); + + R("/_matrix/client/r0/user/(.*)/filter", RouteFilter); + R("/_matrix/client/r0/user/(.*)/filter/(.*)", RouteFilter); + + R("/_matrix/client/r0/createRoom", RouteCreateRoom); + + R("/_matrix/client/r0/directory/room/(.*)", RouteAliasDirectory); + R("/_matrix/client/r0/rooms/(.*)/aliases", RouteRoomAliases); + + + R("/_matrix/client/v3/capabilities", RouteCapabilities); + R("/_matrix/client/v3/login", RouteLogin); + R("/_matrix/client/v3/logout", RouteLogout); + R("/_matrix/client/v3/logout/(all)", RouteLogout); + R("/_matrix/client/v3/register", RouteRegister); + R("/_matrix/client/v3/register/(available)", RouteRegister); + R("/_matrix/client/v3/refresh", RouteRefresh); + + R("/_matrix/client/v3/account/whoami", RouteWhoami); + R("/_matrix/client/v3/account/password", RouteChangePwd); + R("/_matrix/client/v3/account/deactivate", RouteDeactivate); + + R("/_matrix/client/v1/register/m.login.registration_token/validity", RouteTokenValid); + + R("/_matrix/client/v3/account/password/(email|msisdn)/requestToken", RouteRequestToken); + R("/_matrix/client/v3/register/(email|msisdn)/requestToken", RouteRequestToken); + + R("/_matrix/client/v3/profile/(.*)", RouteUserProfile); + R("/_matrix/client/v3/profile/(.*)/(avatar_url|displayname)", RouteUserProfile); + + R("/_matrix/client/v3/user/(.*)/filter", RouteFilter); + R("/_matrix/client/v3/user/(.*)/filter/(.*)", RouteFilter); + + R("/_matrix/client/v3/createRoom", RouteCreateRoom); + + R("/_matrix/client/v3/directory/room/(.*)", RouteAliasDirectory); + R("/_matrix/client/v3/rooms/(.*)/aliases", RouteRoomAliases); + #undef R return router; diff --git a/src/State.c b/src/State.c index 30cbf92..a4134a8 100644 --- a/src/State.c +++ b/src/State.c @@ -237,6 +237,23 @@ StateResolveV2(Array * states) return NULL; } +static HashMap * +StateFromPrevs(Room *room, Array *states) +{ + HashMap *ret_state; + switch (RoomVersionGet(room)) + { + case 1: + ret_state = StateResolveV1(room, states); + break; + default: + ret_state = StateResolveV2(states); + break; + } + + return ret_state; +} + HashMap * StateResolve(Room * room, HashMap * event) { @@ -303,16 +320,7 @@ StateResolve(Room * room, HashMap * event) JsonFree(prevEvent); } - ret_state = NULL; - switch (RoomVersionGet(room)) - { - case 1: - ret_state = StateResolveV1(room, states); - break; - default: - ret_state = StateResolveV2(states); - break; - } + ret_state = StateFromPrevs(room, states); for (i = 0; i < ArraySize(states); i++) { @@ -332,6 +340,49 @@ StateResolve(Room * room, HashMap * event) return ret_state; } +HashMap * +StateCurrent(Room *room) +{ + Array *prevEvents; + Array *states; + size_t i; + HashMap *ret; + if (!room) + { + return NULL; + } + + prevEvents = RoomPrevEventsGet(room); + states = ArrayCreate(); + for (i = 0; i < ArraySize(prevEvents); i++) + { + HashMap *event = + RoomEventFetch(room, JsonValueAsString(ArrayGet(prevEvents, i))); + HashMap *state = StateResolve(room, event); + + if (HashMapGet(event, "state_key")) + { + StateSet( + state, + JsonValueAsString(HashMapGet(event, "type")), + JsonValueAsString(HashMapGet(event, "state_key")), + JsonValueAsString(HashMapGet(event, "event_id"))); + } + + ArrayAdd(states, state); + } + + ret = StateFromPrevs(room, states); + + for (i = 0; i < ArraySize(states); i++) + { + HashMap *state = ArrayGet(states, i); + StateFree(state); + } + ArrayFree(states); + + return ret; +} bool StateIterate(HashMap *state, char **type, char **key, void **event) { char *tuple; diff --git a/src/User.c b/src/User.c index 3a38d34..27a6935 100644 --- a/src/User.c +++ b/src/User.c @@ -945,3 +945,42 @@ UserIdFree(CommonID * id) Free(id); } } + +HashMap * +UserGetTransaction(User *user, char *transaction, char *path) +{ + HashMap *devices; + + if (!user || !transaction || !path) + { + return NULL; + } + + devices = JsonValueAsObject( + HashMapGet(UserGetDevices(user), UserGetDeviceId(user)) + ); + + return JsonDuplicate(JsonValueAsObject( + JsonGet(devices, 3, "transactions", path, transaction) + )); + +} + +void +UserSetTransaction(User *user, char *transaction, char *path, HashMap *resp) +{ + HashMap *devices; + if (!user || !transaction || !path || !resp) + { + return; + } + devices = JsonValueAsObject( + HashMapGet(UserGetDevices(user), UserGetDeviceId(user)) + ); + + /* Overwrite the transaction */ + JsonValueFree(JsonSet( + devices, JsonValueObject(JsonDuplicate(resp)), + 3, "transactions", path, transaction + )); +} diff --git a/src/include/Room.h b/src/include/Room.h index 6a9e0c0..1136d86 100644 --- a/src/include/Room.h +++ b/src/include/Room.h @@ -206,6 +206,11 @@ extern Array * RoomReverseAlias(Db *, char *); */ extern void RoomFreeReverse(Array *); +/** + * Checks whenever a room contains a specific user. + */ +extern bool RoomContainsUser(Room *, char *); + /** * Adds or overwrites a room alias. */ diff --git a/src/include/State.h b/src/include/State.h index 7bc4be4..54d6529 100644 --- a/src/include/State.h +++ b/src/include/State.h @@ -63,6 +63,11 @@ extern bool StateIterate(HashMap *, char **, char **, void **); */ extern HashMap * StateResolve(Room *, HashMap *); +/** + * Computes the current state from the room's leaves. + */ +extern HashMap * StateCurrent(Room *); + /** * Frees an entire state table from the heap. */ diff --git a/src/include/User.h b/src/include/User.h index f03ff39..c83f103 100644 --- a/src/include/User.h +++ b/src/include/User.h @@ -303,6 +303,17 @@ extern int UserDecodePrivilege(const char *); */ extern CommonID * UserIdParse(char *, char *); +/** + * Gets the reply sent to the user from a transaction ID, and an opaque + * ""path"" ID, which is unique per route. + */ +extern HashMap * UserGetTransaction(User *, char *, char *); + +/** + * Stores a transaction for a path with a given response JSON. + */ +extern void UserSetTransaction(User *, char *, char *, HashMap *); + /** * Frees the user's common ID and the memory allocated for it. */