// Server functions which perform operations on room objects.
//
-// Copyright (c) 1987-2023 by the citadel.org team
+// Copyright (c) 1987-2024 by the citadel.org team
//
// This program is open source software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3.
retval = retval | UA_REPLYALLOWED;
}
- // If "collaborative deletion" is active for this room, any user who can post
- // is also allowed to delete
+ // If "collaborative deletion" is active for this room, any user who can post is also allowed to delete
if (roombuf->QRflags2 & QR2_COLLABDEL) {
if (retval & UA_POSTALLOWED) {
retval = retval | UA_DELETEALLOWED;
}
}
-
}
// Check to see if the user has forgotten this room
// CtdlGetRoom() - retrieve room data from disk
int CtdlGetRoom(struct ctdlroom *qrbuf, const char *room_name) {
- struct cdbdata *cdbqr;
+ struct cdbdata cdbqr;
char lowercase_name[ROOMNAMELEN];
char personal_lowercase_name[ROOMNAMELEN];
long len;
cdbqr = cdb_fetch(CDB_ROOMS, lowercase_name, strlen(lowercase_name));
// If that didn't work, try the user's personal namespace
- if (cdbqr == NULL) {
+ if (cdbqr.ptr == NULL) {
snprintf(personal_lowercase_name, sizeof personal_lowercase_name, "%010ld.%s", CC->user.usernum, lowercase_name);
cdbqr = cdb_fetch(CDB_ROOMS, personal_lowercase_name, strlen(personal_lowercase_name));
}
- if (cdbqr != NULL) {
- memcpy(qrbuf, cdbqr->ptr, ((cdbqr->len > sizeof(struct ctdlroom)) ? sizeof(struct ctdlroom) : cdbqr->len));
- cdb_free(cdbqr);
+ if (cdbqr.ptr != NULL) {
+ memcpy(qrbuf, cdbqr.ptr, ((cdbqr.len > sizeof(struct ctdlroom)) ? sizeof(struct ctdlroom) : cdbqr.len));
room_sanity_check(qrbuf);
return (0);
}
int CtdlGetRoomLock(struct ctdlroom *qrbuf, const char *room_name) {
register int retval;
retval = CtdlGetRoom(qrbuf, room_name);
- if (retval == 0) begin_critical_section(S_ROOMS);
+ if (retval == 0) {
+ begin_critical_section(S_ROOMS);
+ }
return(retval);
}
void CtdlPutRoomLock(struct ctdlroom *qrbuf) {
CtdlPutRoom(qrbuf);
end_critical_section(S_ROOMS);
+ //syslog(LOG_ERR, "\033[32mCtdlGetRoomLock(%p) released\033[0m", CC);
}
// CtdlGetFloor() - retrieve floor data from disk
void CtdlGetFloor(struct floor *flbuf, int floor_num) {
- struct cdbdata *cdbfl;
+ struct cdbdata cdbfl;
memset(flbuf, 0, sizeof(struct floor));
cdbfl = cdb_fetch(CDB_FLOORTAB, &floor_num, sizeof(int));
- if (cdbfl != NULL) {
- memcpy(flbuf, cdbfl->ptr, ((cdbfl->len > sizeof(struct floor)) ? sizeof(struct floor) : cdbfl->len));
- cdb_free(cdbfl);
+ if (cdbfl.ptr != NULL) {
+ memcpy(flbuf, cdbfl.ptr, ((cdbfl.len > sizeof(struct floor)) ? sizeof(struct floor) : cdbfl.len));
}
else {
if (floor_num == 0) {
for (i=0; i<MAXFLOORS; ++i) {
floorcache[floor_num] = NULL;
}
- initialized = 1;
+ initialized = 1;
}
if (floorcache[floor_num] == NULL) {
fetch_new = 1;
memcpy(floorcache[floor_num], flbuf, sizeof(struct floor));
}
end_critical_section(S_FLOORCACHE);
-
- cdb_store(CDB_FLOORTAB, &floor_num, sizeof(int),
- flbuf, sizeof(struct floor));
+ cdb_store(CDB_FLOORTAB, &floor_num, sizeof(int), flbuf, sizeof(struct floor));
}
// Iterate through the room table, performing a callback for each room.
void CtdlForEachRoom(ForEachRoomCallBack callback_func, void *in_data) {
struct ctdlroom qrbuf;
- struct cdbdata *cdbqr;
+ struct cdbkeyval cdbqr;
cdb_rewind(CDB_ROOMS);
- while (cdbqr = cdb_next_item(CDB_ROOMS), cdbqr != NULL) {
+ while (cdbqr = cdb_next_item(CDB_ROOMS), cdbqr.val.ptr!=NULL) { // always read through to the end
memset(&qrbuf, 0, sizeof(struct ctdlroom));
- memcpy(&qrbuf, cdbqr->ptr, ((cdbqr->len > sizeof(struct ctdlroom)) ? sizeof(struct ctdlroom) : cdbqr->len) );
- cdb_free(cdbqr);
+ memcpy(&qrbuf, cdbqr.val.ptr, ((cdbqr.val.len > sizeof(struct ctdlroom)) ? sizeof(struct ctdlroom) : cdbqr.val.len) );
room_sanity_check(&qrbuf);
if (qrbuf.QRflags & QR_INUSE) {
callback_func(&qrbuf, in_data);
// delete_msglist() - delete room message pointers
void delete_msglist(struct ctdlroom *whichroom) {
- struct cdbdata *cdbml;
+ struct cdbdata cdbml;
- // Make sure the msglist we're deleting actually exists, otherwise
- // libdb will complain when we try to delete an invalid record
+ // Make sure the msglist we're deleting actually exists; don't try to delete an invalid record
cdbml = cdb_fetch(CDB_MSGLISTS, &whichroom->QRnumber, sizeof(long));
- if (cdbml != NULL) {
- cdb_free(cdbml);
-
- // Go ahead and delete it
+ if (cdbml.ptr != NULL) {
+ // ok it exists, go ahead and delete it
cdb_delete(CDB_MSGLISTS, &whichroom->QRnumber, sizeof(long));
}
}
}
+// Retrieve a list of all messages (message numbers) in the specified room.
+// Returns the number of messages in the room, allocates a pointer to the array and stuffs it in the supplied location.
+// Caller must free that memory.
+// If no messages in room, returns 0 and msgs is set to NULL.
+int CtdlFetchMsgList(long roomnum, long **msgs) {
+ int num_msgs = 0;
+ struct cdbdata cdbfr;
+
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &roomnum, sizeof(long));
+ if (cdbfr.ptr == NULL) {
+ *msgs = malloc(sizeof(long)); // dummy buffer
+ *msgs[0] = 0;
+ return (0);
+ }
+
+ num_msgs = cdbfr.len / sizeof(long);
+ if (num_msgs > 0) {
+ *msgs = malloc(cdbfr.len);
+ memcpy(*msgs, cdbfr.ptr, cdbfr.len);
+ }
+ else {
+ *msgs = NULL;
+ }
+ return(num_msgs);
+}
+
+
// Make the specified room the current room for this session. No validation
// or access control is done here -- the caller should make sure that the
// specified room exists and is ok to access.
int raideflag;
struct visit vbuf;
char truncated_roomname[ROOMNAMELEN];
- struct cdbdata *cdbfr;
long *msglist = NULL;
int num_msgs = 0;
unsigned int original_v_flags;
info = 1;
}
- cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
- if (cdbfr != NULL) {
- msglist = (long *) cdbfr->ptr;
- cdbfr->ptr = NULL; // CtdlUserGoto() now owns this memory (this requires attention if we move to LMDB)
- num_msgs = cdbfr->len / sizeof(long);
- cdb_free(cdbfr);
- }
+ num_msgs = CtdlFetchMsgList(CC->room.QRnumber, &msglist);
total_messages = 0;
for (a=0; a<num_msgs; ++a) {
if (display_result) {
cprintf("%d%c%s|%d|%d|%d|%d|%ld|%ld|%d|%d|%d|%d|%d|%d|%d|%d|%ld|\n",
- CIT_OK, CtdlCheckExpress(),
+ CIT_OK, CtdlCheckExpress(CC),
truncated_roomname,
(int)new_messages,
(int)total_messages,
qrbuf.QRfloor = new_floor;
CtdlPutRoom(&qrbuf);
- begin_critical_section(S_CONFIG);
-
- // If baseroom/aideroom name changes, update config
- if (!strncasecmp(old_name, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN)) {
- CtdlSetConfigStr("c_baseroom", new_name);
- }
- if (!strncasecmp(old_name, CtdlGetConfigStr("c_aideroom"), ROOMNAMELEN)) {
- CtdlSetConfigStr("c_aideroom", new_name);
- }
-
- end_critical_section(S_CONFIG);
// If the room name changed, then there are now two room
// records, so we have to delete the old one.
end_critical_section(S_ROOMS);
+ // If baseroom/aideroom name changes, update config
+ begin_critical_section(S_CONFIG);
+ if (!strncasecmp(old_name, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN)) {
+ CtdlSetConfigStr("c_baseroom", new_name);
+ }
+ if (!strncasecmp(old_name, CtdlGetConfigStr("c_aideroom"), ROOMNAMELEN)) {
+ CtdlSetConfigStr("c_aideroom", new_name);
+ }
+ end_critical_section(S_CONFIG);
+
// Adjust the floor reference counts if necessary
if (new_floor != old_floor) {
lgetfloor(&flbuf, old_floor);