diff --git a/src/Room.c b/src/Room.c index c17499a..9fc0994 100644 --- a/src/Room.c +++ b/src/Room.c @@ -78,48 +78,15 @@ GenerateRoomId(ServerPart s) return string; } - -Room * -RoomCreate(Db * db, User *user, RoomCreateRequest * req, ServerPart s) +static void +RoomPopulate(Room *room, User *user, RoomCreateRequest *req, ServerPart s) { - Room *room; - char *version_string, *full_creator; - int version_num = 1; - HashMap *json; - HashMap *event, *content; CommonID sender; char *sender_str, *key; - JsonValue *val; - HashMap *override; + HashMap *content, *event, *override; Array *initial_states; + JsonValue *val; size_t i; - if (!db || !req || !user) - { - return NULL; - } - - version_string = req->room_version; - if (version_string) - { - /* TODO: Eventually use something else than room version 1 by - * default, and maybe add a config parameter. */ - version_num = atoi(version_string); - version_num = version_num == 0 ? 1 : version_num; - } - room = Malloc(sizeof(Room)); - room->db = db; - room->creator.hostname = s.hostname ? StrDuplicate(s.hostname) : NULL; - room->creator.port = s.port ? StrDuplicate(s.port) : NULL; - room->id = GenerateRoomId(s); - room->version = version_num; - - room->state_ref = DbCreate(db, 3, "rooms", room->id, "state"); - room->leaves_ref = DbCreate(db, 3, "rooms", room->id, "leaves"); - json = DbJson(room->leaves_ref); - JsonSet(json, JsonValueArray(ArrayCreate()), 1, "leaves"); - full_creator = ParserRecomposeServerPart(room->creator); - JsonSet(json, JsonValueString(full_creator), 1, "creator"); - Free(full_creator); sender.sigil = '@'; sender.local = UserGetName(user); @@ -164,8 +131,21 @@ RoomCreate(Db * db, User *user, RoomCreateRequest * req, ServerPart s) JsonFree(RoomEventSend(room, event)); JsonFree(event); - /* TODO: Events set by the preset */ - /* TODO: Events in initial_state */ + /* Presets */ + switch (req->preset) + { + case ROOM_CREATE_PUBLIC: + /* TODO */ + break; + case ROOM_CREATE_TRUSTED: + /* TODO */ + break; + case ROOM_CREATE_PRIVATE: + /* TODO */ + break; + } + + /* User-provided initial states */ initial_states = req->initial_state; for (i = 0; i < ArraySize(initial_states); i++) { @@ -181,6 +161,8 @@ RoomCreate(Db * db, User *user, RoomCreateRequest * req, ServerPart s) JsonFree(RoomEventSend(room, rseObject)); JsonFree(rseObject); } + + /* Name and topic. */ if (req->name) { content = HashMapCreate(); @@ -197,10 +179,112 @@ RoomCreate(Db * db, User *user, RoomCreateRequest * req, ServerPart s) JsonFree(RoomEventSend(room, event)); JsonFree(event); } + + /* Custom alias */ + if (req->room_alias_name) + { + DbRef *aliasesRef = DbLock(room->db, 1, "aliases"); + HashMap *aliasesJson; + if (!aliasesRef) + { + aliasesRef = DbCreate(room->db, 1, "aliases"); + } + + if (aliasesRef) + { + CommonID full; + char *fullStr, *serverStr; + HashMap *alias, *idObject; + Array *servers, *ids; + + full.sigil = '#'; + full.local = req->room_alias_name; + full.server = s; + + aliasesJson = DbJson(aliasesRef); + fullStr = ParserRecomposeCommonID(full); + + servers = ArrayCreate(); + serverStr = ParserRecomposeServerPart(room->creator); + ArrayAdd(servers, JsonValueString(serverStr)); + Free(serverStr); + + alias = HashMapCreate(); + HashMapSet(alias, "createdBy", JsonValueString(sender_str)); + HashMapSet(alias, "id", JsonValueString(room->id)); + HashMapSet(alias, "servers", JsonValueArray(servers)); + + JsonValueFree(JsonSet( + aliasesJson, JsonValueObject(alias), 2, + "aliases", fullStr)); + if (!(idObject = + JsonValueAsObject(JsonGet(aliasesJson, 2, "id", room->id)))) + { + ids = ArrayCreate(); + idObject = HashMapCreate(); + HashMapSet(idObject, "aliases", JsonValueArray(ids)); + JsonSet( + aliasesJson, + JsonValueObject(idObject), + 2, "id", room->id); + } + ids = JsonValueAsArray(HashMapGet(idObject, "aliases")); + ArrayAdd(ids, JsonValueString(fullStr)); + + content = HashMapCreate(); + JsonSet(content, JsonValueString(fullStr), 1, "alias"); + event = RoomEventCreate( + sender_str, + "m.room.canonical_alias", "", content); + JsonFree(RoomEventSend(room, event)); + JsonFree(event); + + Free(fullStr); + DbUnlock(room->db, aliasesRef); + } + } /* TODO: The rest of the events mandated by the specification on - * POST /createRoom. */ + * POST /createRoom, and error management. */ Free(sender_str); +} +Room * +RoomCreate(Db * db, User *user, RoomCreateRequest * req, ServerPart s) +{ + Room *room; + char *version_string, *full_creator; + int version_num = 1; + HashMap *json; + if (!db || !req || !user) + { + return NULL; + } + + version_string = req->room_version; + if (version_string) + { + /* TODO: Eventually use something else than room version 1 by + * default, and maybe add a config parameter. */ + version_num = atoi(version_string); + version_num = version_num == 0 ? 1 : version_num; + } + room = Malloc(sizeof(Room)); + room->db = db; + room->creator.hostname = s.hostname ? StrDuplicate(s.hostname) : NULL; + room->creator.port = s.port ? StrDuplicate(s.port) : NULL; + room->id = GenerateRoomId(s); + room->version = version_num; + + room->state_ref = DbCreate(db, 3, "rooms", room->id, "state"); + room->leaves_ref = DbCreate(db, 3, "rooms", room->id, "leaves"); + json = DbJson(room->leaves_ref); + JsonSet(json, JsonValueArray(ArrayCreate()), 1, "leaves"); + full_creator = ParserRecomposeServerPart(room->creator); + JsonSet(json, JsonValueString(full_creator), 1, "creator"); + Free(full_creator); + + RoomPopulate(room, user, req, s); + return room; } @@ -499,9 +583,8 @@ PopulateEventV1(Room * room, HashMap * event, PduV1 * pdu, ServerPart serv) pdu->room_id = StrDuplicate(room->id); pdu->signatures = HashMapCreate(); pdu->depth = RoomGetDepth(room) + 1; /* TODO: Clamp this value. */ - pdu->depth = - pdu->depth >= (int64_t) UINT64_MAX ? - (int64_t) UINT64_MAX : pdu->depth; + pdu->depth = pdu->depth >= (int64_t) INT64_MAX ? + (int64_t) INT64_MAX : pdu->depth; /* Create a random event ID for this PDU. * TODO: Optionally verify whenever it's already used, but that