X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Froom_ops.c;h=5b358b609bb88c175dc5c43b95964512e01aab95;hb=a4570bee71e9c8797b6d50ec1644efd234377707;hp=0d90bc3b300ea0eb7bb73dce6565f95e8fd56bdc;hpb=99162a9246e13881e4bd1809b2c3332acc407d08;p=citadel.git diff --git a/citadel/room_ops.c b/citadel/room_ops.c index 0d90bc3b3..5b358b609 100644 --- a/citadel/room_ops.c +++ b/citadel/room_ops.c @@ -1,7 +1,7 @@ /* * Server functions which perform operations on room objects. * - * Copyright (c) 1987-2012 by the citadel.org team + * Copyright (c) 1987-2016 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. @@ -12,44 +12,15 @@ * GNU General Public License for more details. */ -#include "sysdep.h" -#include -#include #include -#include -#include -#include -#include /* for cmd_rdir to read contents of the directory */ - -#if TIME_WITH_SYS_TIME -# include -# include -#else -# if HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif - -#include -#include -#include "citadel.h" #include -#include "server.h" -#include "database.h" -#include "config.h" -#include "room_ops.h" -#include "sysdep_decls.h" -#include "support.h" -#include "msgbase.h" -#include "citserver.h" -#include "control.h" -#include "citadel_dirs.h" -#include "threads.h" +#include "citserver.h" #include "ctdl_module.h" +#include "config.h" +#include "control.h" #include "user_ops.h" +#include "room_ops.h" struct floor *floorcache[MAXFLOORS]; @@ -60,7 +31,7 @@ struct floor *floorcache[MAXFLOORS]; int CtdlDoIHavePermissionToReadMessagesInThisRoom(void) { if ( (!(CC->logged_in)) && (!(CC->internal_pgm)) - && (!config.c_guest_logins) + && (!CtdlGetConfigInt("c_guest_logins")) ) { return(om_not_logged_in); } @@ -107,8 +78,8 @@ int CtdlDoIHavePermissionToPostInThisRoom( } - if ((CC->user.axlevel < AxProbU) - && ((CC->room.QRflags & QR_MAILBOX) == 0)) { + if ((CC->user.axlevel < AxProbU) && ((CC->room.QRflags & QR_MAILBOX) == 0)) + { snprintf(errmsgbuf, n, "Need to be validated to enter (except in %s> to sysop)", MAILROOM); return (ERROR + HIGHER_ACCESS_REQUIRED); } @@ -153,7 +124,8 @@ int CtdlDoIHavePermissionToDeleteMessagesFromThisRoom(void) { } /* - * Retrieve access control information for any user/room pair + * Retrieve access control information for any user/room pair. + * Yes, it has a couple of gotos. If you don't like that, go die in a car fire. */ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, int *result, int *view) @@ -167,7 +139,7 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, is_me = 1; } - if ((is_me) && (config.c_guest_logins) && (!CC->logged_in)) { + if ((is_me) && (CtdlGetConfigInt("c_guest_logins")) && (!CC->logged_in)) { is_guest = 1; } @@ -194,7 +166,7 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, } /* Force the properties of the Aide room */ - if (!strcasecmp(roombuf->QRname, config.c_aideroom)) { + if (!strcasecmp(roombuf->QRname, CtdlGetConfigStr("c_aideroom"))) { if (userbuf->axlevel >= AxAideU) { retval = UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED | UA_REPLYALLOWED; } else { @@ -366,11 +338,12 @@ void room_sanity_check(struct ctdlroom *qrbuf) } /* Listing order of 0 is illegal except for base rooms */ if (qrbuf->QRorder == 0) - if (!(qrbuf->QRflags & QR_MAILBOX) && - strncasecmp(qrbuf->QRname, config.c_baseroom, ROOMNAMELEN) - && - strncasecmp(qrbuf->QRname, config.c_aideroom, ROOMNAMELEN)) + if ( !(qrbuf->QRflags & QR_MAILBOX) + && strncasecmp(qrbuf->QRname, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN) + && strncasecmp(qrbuf->QRname, CtdlGetConfigStr("c_aideroom"), ROOMNAMELEN) + ) { qrbuf->QRorder = 64; + } } @@ -423,10 +396,11 @@ int CtdlGetRoom(struct ctdlroom *qrbuf, const char *room_name) } } + /* * CtdlGetRoomLock() - same as getroom() but locks the record (if supported) */ -int CtdlGetRoomLock(struct ctdlroom *qrbuf, char *room_name) +int CtdlGetRoomLock(struct ctdlroom *qrbuf, const char *room_name) { register int retval; retval = CtdlGetRoom(qrbuf, room_name); @@ -486,10 +460,8 @@ void b_deleteroom(char *room_name) { */ void CtdlPutRoomLock(struct ctdlroom *qrbuf) { - CtdlPutRoom(qrbuf); end_critical_section(S_ROOMS); - } @@ -578,7 +550,6 @@ void CtdlGetFloor(struct floor *flbuf, int floor_num) */ void lgetfloor(struct floor *flbuf, int floor_num) { - begin_critical_section(S_FLOORTAB); CtdlGetFloor(flbuf, floor_num); } @@ -646,7 +617,6 @@ void CtdlPutFloor(struct floor *flbuf, int floor_num) */ void CtdlPutFloorLock(struct floor *flbuf, int floor_num) { - CtdlPutFloor(flbuf, floor_num); end_critical_section(S_FLOORTAB); @@ -663,7 +633,7 @@ void lputfloor(struct floor *flbuf, int floor_num) /* - * Traverse the room file... + * Iterate through the room table, performing a callback for each room. */ void CtdlForEachRoom(ForEachRoomCallBack CB, void *in_data) { @@ -687,11 +657,9 @@ void CtdlForEachRoom(ForEachRoomCallBack CB, void *in_data) } /* - * Traverse the room file... + * Iterate through the room table, performing a callback for each room that has a netconfig entry. */ -void CtdlForEachNetCfgRoom(ForEachRoomNetCfgCallBack CB, - void *in_data, - RoomNetCfg filter) +void CtdlForEachNetCfgRoom(ForEachRoomNetCfgCallBack CB, void *in_data) { struct ctdlroom qrbuf; struct cdbdata *cdbqr; @@ -700,21 +668,17 @@ void CtdlForEachNetCfgRoom(ForEachRoomNetCfgCallBack CB, while (cdbqr = cdb_next_item(CDB_ROOMS), cdbqr != NULL) { memset(&qrbuf, 0, sizeof(struct ctdlroom)); - memcpy(&qrbuf, cdbqr->ptr, - ((cdbqr->len > sizeof(struct ctdlroom)) ? - sizeof(struct ctdlroom) : cdbqr->len) - ); + memcpy(&qrbuf, cdbqr->ptr, ((cdbqr->len > sizeof(struct ctdlroom)) ? sizeof(struct ctdlroom) : cdbqr->len)); cdb_free(cdbqr); room_sanity_check(&qrbuf); if (qrbuf.QRflags & QR_INUSE) { - OneRoomNetCfg* RNCfg; + OneRoomNetCfg *RNCfg; RNCfg = CtdlGetNetCfgForRoom(qrbuf.QRnumber); - if ((RNCfg != NULL) && - ((filter == maxRoomNetCfg) || - (RNCfg->NetConfigs[filter] != NULL))) + if (RNCfg != NULL) { CB(&qrbuf, in_data, RNCfg); + FreeRoomNetworkStruct(&RNCfg); } } } @@ -804,13 +768,15 @@ int CtdlIsNonEditable(struct ctdlroom *qrbuf) * specified room exists and is ok to access. */ void CtdlUserGoto(char *where, int display_result, int transiently, - int *retmsgs, int *retnew) + int *retmsgs, int *retnew, long *retoldest, long *retnewest) { struct CitContext *CCC = CC; int a; int new_messages = 0; int old_messages = 0; int total_messages = 0; + long oldest_message = 0; + long newest_message = 0; int info = 0; int rmailflag; int raideflag; @@ -845,8 +811,8 @@ void CtdlUserGoto(char *where, int display_result, int transiently, /* Know the room ... but not if it's the page log room, or if the * caller specified that we're only entering this room transiently. */ - if ((strcasecmp(CCC->room.QRname, config.c_logpages)) - && (transiently == 0) ) { + if ((strcasecmp(CCC->room.QRname, CtdlGetConfigStr("c_logpages"))) && (transiently == 0)) + { vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT; vbuf.v_flags = vbuf.v_flags | V_ACCESS; } @@ -860,8 +826,10 @@ void CtdlUserGoto(char *where, int display_result, int transiently, /* Check for new mail */ newmailcount = NewMailCount(); - /* set info to 1 if the user needs to read the room's info file */ - if (CCC->room.QRinfo > vbuf.v_lastseen) { + /* Set info to 1 if the room banner is new since our last visit. + * Some clients only want to display it when it changes. + */ + if (CCC->room.msgnum_info > vbuf.v_lastseen) { info = 1; } @@ -878,6 +846,11 @@ void CtdlUserGoto(char *where, int display_result, int transiently, if (msglist[a] > 0L) ++total_messages; } + if (total_messages > 0) { + oldest_message = msglist[0]; + newest_message = msglist[num_msgs - 1]; + } + num_sets = num_tokens(vbuf.v_seen, ','); for (s=0; s %d new of %d total messages\n", - CCC->room.QRname, - new_messages, total_messages - ); + if (retoldest != NULL) *retoldest = oldest_message; + if (retnewest != NULL) *retnewest = newest_message; + MSG_syslog(LOG_DEBUG, "<%s> %d new of %d total messages, oldest=%ld, newest=%ld", + CCC->room.QRname, new_messages, total_messages, oldest_message, newest_message + ); CCC->curr_view = (int)vbuf.v_view; @@ -965,7 +939,7 @@ void CtdlUserGoto(char *where, int display_result, int transiently, */ void convert_room_name_macros(char *towhere, size_t maxlen) { if (!strcasecmp(towhere, "_BASEROOM_")) { - safestrncpy(towhere, config.c_baseroom, maxlen); + safestrncpy(towhere, CtdlGetConfigStr("c_baseroom"), maxlen); } else if (!strcasecmp(towhere, "_MAIL_")) { safestrncpy(towhere, MAILROOM, maxlen); @@ -977,7 +951,7 @@ void convert_room_name_macros(char *towhere, size_t maxlen) { safestrncpy(towhere, USERDRAFTROOM, maxlen); } else if (!strcasecmp(towhere, "_BITBUCKET_")) { - safestrncpy(towhere, config.c_twitroom, maxlen); + safestrncpy(towhere, CtdlGetConfigStr("c_twitroom"), maxlen); } else if (!strcasecmp(towhere, "_CALENDAR_")) { safestrncpy(towhere, USERCALENDARROOM, maxlen); @@ -1003,6 +977,7 @@ void convert_room_name_macros(char *towhere, size_t maxlen) { * in *at least* the old name! */ int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) { + struct CitContext *CCC = CC; int old_floor = 0; struct ctdlroom qrbuf; struct ctdlroom qrtmp; @@ -1012,8 +987,7 @@ int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) { long owner = 0L; char actual_old_name[ROOMNAMELEN]; - syslog(LOG_DEBUG, "CtdlRenameRoom(%s, %s, %d)\n", - old_name, new_name, new_floor); + MSG_syslog(LOG_DEBUG, "CtdlRenameRoom(%s, %s, %d)", old_name, new_name, new_floor); if (new_floor >= 0) { fl = CtdlGetCachedFloor(new_floor); @@ -1033,9 +1007,9 @@ int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) { ret = crr_room_not_found; } - else if ( (CC->user.axlevel < AxAideU) && (!CC->internal_pgm) - && (CC->user.usernum != qrbuf.QRroomaide) - && ( (((qrbuf.QRflags & QR_MAILBOX) == 0) || (atol(qrbuf.QRname) != CC->user.usernum))) ) { + else if ( (CCC->user.axlevel < AxAideU) && (!CCC->internal_pgm) + && (CCC->user.usernum != qrbuf.QRroomaide) + && ( (((qrbuf.QRflags & QR_MAILBOX) == 0) || (atol(qrbuf.QRname) != CCC->user.usernum))) ) { ret = crr_access_denied; } @@ -1059,8 +1033,9 @@ int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) { } /* Reject change of floor for baseroom/aideroom */ - if (!strncasecmp(old_name, config.c_baseroom, ROOMNAMELEN) || - !strncasecmp(old_name, config.c_aideroom, ROOMNAMELEN)) { + if (!strncasecmp(old_name, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN) || + !strncasecmp(old_name, CtdlGetConfigStr("c_aideroom"), ROOMNAMELEN)) + { new_floor = 0; } @@ -1075,13 +1050,11 @@ int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) { begin_critical_section(S_CONFIG); /* If baseroom/aideroom name changes, update config */ - if (!strncasecmp(old_name, config.c_baseroom, ROOMNAMELEN)) { - safestrncpy(config.c_baseroom, new_name, ROOMNAMELEN); - put_config(); + if (!strncasecmp(old_name, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN)) { + CtdlSetConfigStr("c_baseroom", new_name); } - if (!strncasecmp(old_name, config.c_aideroom, ROOMNAMELEN)) { - safestrncpy(config.c_aideroom, new_name, ROOMNAMELEN); - put_config(); + if (!strncasecmp(old_name, CtdlGetConfigStr("c_aideroom"), ROOMNAMELEN)) { + CtdlSetConfigStr("c_aideroom", new_name); } end_critical_section(S_CONFIG); @@ -1103,11 +1076,11 @@ int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) { lgetfloor(&flbuf, old_floor); --flbuf.f_ref_count; lputfloor(&flbuf, old_floor); - syslog(LOG_DEBUG, "Reference count for floor %d is now %d\n", old_floor, flbuf.f_ref_count); + MSG_syslog(LOG_DEBUG, "Reference count for floor %d is now %d", old_floor, flbuf.f_ref_count); lgetfloor(&flbuf, new_floor); ++flbuf.f_ref_count; lputfloor(&flbuf, new_floor); - syslog(LOG_DEBUG, "Reference count for floor %d is now %d\n", new_floor, flbuf.f_ref_count); + MSG_syslog(LOG_DEBUG, "Reference count for floor %d is now %d", new_floor, flbuf.f_ref_count); } /* ...and everybody say "YATTA!" */ @@ -1115,22 +1088,20 @@ int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) { } - /* - * Asynchronously schedule a room for deletion. The room will appear - * deleted to the user(s), but it won't actually get purged from the - * database until THE DREADED AUTO-PURGER makes its next run. + * Asynchronously schedule a room for deletion. By placing the room into an invalid private namespace, + * the room will appear deleted to the user(s), but the session doesn't need to block while waiting for + * database operations to complete. Instead, the room gets purged when THE DREADED AUTO-PURGER makes + * its next run. Aren't we so clever?!! */ void CtdlScheduleRoomForDeletion(struct ctdlroom *qrbuf) { char old_name[ROOMNAMELEN]; static int seq = 0; - syslog(LOG_NOTICE, "Scheduling room <%s> for deletion\n", - qrbuf->QRname); + syslog(LOG_NOTICE, "Scheduling room <%s> for deletion", qrbuf->QRname); safestrncpy(old_name, qrbuf->QRname, sizeof old_name); - CtdlGetRoom(qrbuf, qrbuf->QRname); /* Turn the room into a private mailbox owned by a user who doesn't @@ -1144,9 +1115,7 @@ void CtdlScheduleRoomForDeletion(struct ctdlroom *qrbuf) ); qrbuf->QRflags |= QR_MAILBOX; time(&qrbuf->QRgen); /* Use a timestamp as the new generation number */ - CtdlPutRoom(qrbuf); - b_deleteroom(old_name); } @@ -1161,22 +1130,13 @@ void CtdlScheduleRoomForDeletion(struct ctdlroom *qrbuf) void CtdlDeleteRoom(struct ctdlroom *qrbuf) { struct floor flbuf; - char filename[100]; - /* TODO: filename magic? does this realy work? */ - - syslog(LOG_NOTICE, "Deleting room <%s>\n", qrbuf->QRname); + char configdbkeyname[25]; - /* Delete the info file */ - assoc_file_name(filename, sizeof filename, qrbuf, ctdl_info_dir); - unlink(filename); + syslog(LOG_NOTICE, "Deleting room <%s>", qrbuf->QRname); - /* Delete the image file */ - assoc_file_name(filename, sizeof filename, qrbuf, ctdl_image_dir); - unlink(filename); - - /* Delete the room's network config file */ - assoc_file_name(filename, sizeof filename, qrbuf, ctdl_netcfg_dir); - unlink(filename); + /* Delete the room's network configdb entry */ + netcfg_keyname(configdbkeyname, qrbuf->QRnumber); + CtdlDelConfig(configdbkeyname); /* Delete the messages in the room * (Careful: this opens an S_ROOMS critical section!) @@ -1198,7 +1158,6 @@ void CtdlDeleteRoom(struct ctdlroom *qrbuf) } - /* * Check access control for deleting a room */ @@ -1257,11 +1216,10 @@ unsigned CtdlCreateRoom(char *new_room_name, struct floor flbuf; visit vbuf; - syslog(LOG_DEBUG, "CtdlCreateRoom(name=%s, type=%d, view=%d)\n", - new_room_name, new_room_type, new_room_view); + MARK_syslog(LOG_DEBUG, "CtdlCreateRoom(name=%s, type=%d, view=%d)", new_room_name, new_room_type, new_room_view); if (CtdlGetRoom(&qrbuf, new_room_name) == 0) { - syslog(LOG_DEBUG, "%s already exists.\n", new_room_name); + MARK_syslog(LOG_DEBUG, "Cannot create room <%s> - already exists", new_room_name); return(0); }