* Holy war on strlen: use IsEmptyStr where apropriate.
[citadel.git] / citadel / room_ops.c
index 80fada02cd0ba74dbb11f610f163f882f11410a5..340b99a38dd2b786383766152f32383c8b1fc4d4 100644 (file)
@@ -5,10 +5,6 @@
  *
  */
 
-#ifdef DLL_EXPORT
-#define IN_LIBCIT
-#endif
-
 #include "sysdep.h"
 #include <stdlib.h>
 #include <unistd.h>
@@ -32,7 +28,6 @@
 #include <errno.h>
 #include "citadel.h"
 #include "server.h"
-#include "serv_extensions.h"
 #include "database.h"
 #include "config.h"
 #include "room_ops.h"
 #include "citserver.h"
 #include "control.h"
 #include "tools.h"
+#include "citadel_dirs.h"
 
 struct floor *floorcache[MAXFLOORS];
 
 /*
- * Generic routine for determining user access to rooms
+ * Retrieve access control information for any user/room pair
  */
 void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf,
                int *result, int *view)
@@ -57,7 +53,7 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf,
 
        /* for internal programs, always do everything */
        if (((CC->internal_pgm)) && (roombuf->QRflags & QR_INUSE)) {
-               retval = (UA_KNOWN | UA_GOTOALLOWED);
+               retval = (UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED);
                vbuf.v_view = 0;
                goto SKIP_EVERYTHING;
        }
@@ -68,7 +64,7 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf,
        /* Force the properties of the Aide room */
        if (!strcasecmp(roombuf->QRname, config.c_aideroom)) {
                if (userbuf->axlevel >= 6) {
-                       retval = UA_KNOWN | UA_GOTOALLOWED;
+                       retval = UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED;
                } else {
                        retval = 0;
                }
@@ -106,15 +102,43 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf,
                }
        }
 
-       /* For mailbox rooms, also check the generation number matchups */
+       /* For mailbox rooms, also check the namespace */
+       /* Also, mailbox owners can delete their messages */
        if (roombuf->QRflags & QR_MAILBOX) {
                if (userbuf->usernum == atol(roombuf->QRname)) {
-                       retval = retval | UA_KNOWN | UA_GOTOALLOWED;
+                       retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED;
                }
                /* An explicit match means the user belongs in this room */
                if (vbuf.v_flags & V_ACCESS) {
-                       retval = retval | UA_KNOWN | UA_GOTOALLOWED;
+                       retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED;
+               }
+       }
+
+       /* For non-mailbox rooms... */
+       else {
+
+               /* User is allowed to post in the room unless:
+                * - User is not validated
+                * - User has no net privileges and it is a shared network room
+                * - It is a read-only room
+                */
+               int post_allowed = 1;
+               if (CC->user.axlevel < 2) post_allowed = 0;
+               if ((CC->user.axlevel < 4) && (CC->room.QRflags & QR_NETWORK)) post_allowed = 0;
+               if (roombuf->QRflags & QR_READONLY) post_allowed = 0;
+               if (post_allowed) {
+                       retval = retval | UA_POSTALLOWED;
                }
+
+               /* If "collaborative deletion" is active for this room, any user who can post
+                * is also allowed to delete
+                */
+               if (CC->room.QRflags2 & QR2_COLLABDEL) {
+                       if (retval & UA_POSTALLOWED) {
+                               retval = retval | UA_DELETEALLOWED;
+                       }
+               }
+
        }
 
        /* Check to see if the user has forgotten this room */
@@ -129,17 +153,17 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf,
        }
        /* If user is explicitly locked out of this room, deny everything */
        if (vbuf.v_flags & V_LOCKOUT) {
-               retval = retval & ~UA_KNOWN & ~UA_GOTOALLOWED;
+               retval = retval & ~UA_KNOWN & ~UA_GOTOALLOWED & ~UA_POSTALLOWED;
        }
 
        /* Aides get access to all private rooms */
        if ( (userbuf->axlevel >= 6)
           && ((roombuf->QRflags & QR_MAILBOX) == 0) ) {
                if (vbuf.v_flags & V_FORGET) {
-                       retval = retval | UA_GOTOALLOWED;
+                       retval = retval | UA_GOTOALLOWED | UA_POSTALLOWED;
                }
                else {
-                       retval = retval | UA_KNOWN | UA_GOTOALLOWED;
+                       retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED;
                }
        }
 
@@ -148,7 +172,14 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf,
         */
        if ( (userbuf->axlevel >= 6)
           && (roombuf->QRflags & QR_MAILBOX) ) {
-               retval = retval | UA_GOTOALLOWED;
+               retval = retval | UA_GOTOALLOWED | UA_POSTALLOWED;
+       }
+
+       /* Aides and Room Aides have admin privileges */
+       if ( (userbuf->axlevel >= 6)
+          || (userbuf->usernum == roombuf->QRroomaide)
+          ) {
+               retval = retval | UA_ADMINALLOWED | UA_DELETEALLOWED;
        }
 
 NEWMSG:        /* By the way, we also check for the presence of new messages */
@@ -506,7 +537,7 @@ int is_noneditable(struct ctdlroom *qrbuf)
 /*
  * Back-back-end for all room listing commands
  */
-void list_roomname(struct ctdlroom *qrbuf, int ra, int view)
+void list_roomname(struct ctdlroom *qrbuf, int ra, int current_view, int default_view)
 {
        char truncated_roomname[ROOMNAMELEN];
 
@@ -523,13 +554,15 @@ void list_roomname(struct ctdlroom *qrbuf, int ra, int view)
        }
 
        /* ...and now the other parameters */
-       cprintf("|%u|%d|%d|%d|%d|%d|\n",
+       cprintf("|%u|%d|%d|%d|%d|%d|%d|%ld|\n",
                qrbuf->QRflags,
                (int) qrbuf->QRfloor,
                (int) qrbuf->QRorder,
                (int) qrbuf->QRflags2,
                ra,
-               view
+               current_view,
+               default_view,
+               qrbuf->QRmtime
        );
 }
 
@@ -549,13 +582,13 @@ void cmd_lrms_backend(struct ctdlroom *qrbuf, void *data)
        if ((( ra & (UA_KNOWN | UA_ZAPPED)))
            && ((qrbuf->QRfloor == (FloorBeingSearched))
                || ((FloorBeingSearched) < 0)))
-               list_roomname(qrbuf, ra, view);
+               list_roomname(qrbuf, ra, view, qrbuf->QRdefaultview);
 }
 
 void cmd_lrms(char *argbuf)
 {
        int FloorBeingSearched = (-1);
-       if (strlen(argbuf) > 0)
+       if (!IsEmptyStr(argbuf))
                FloorBeingSearched = extract_int(argbuf, 0);
 
        if (CtdlAccessCheck(ac_logged_in)) return;
@@ -587,13 +620,13 @@ void cmd_lkra_backend(struct ctdlroom *qrbuf, void *data)
        if ((( ra & (UA_KNOWN)))
            && ((qrbuf->QRfloor == (FloorBeingSearched))
                || ((FloorBeingSearched) < 0)))
-               list_roomname(qrbuf, ra, view);
+               list_roomname(qrbuf, ra, view, qrbuf->QRdefaultview);
 }
 
 void cmd_lkra(char *argbuf)
 {
        int FloorBeingSearched = (-1);
-       if (strlen(argbuf) > 0)
+       if (!IsEmptyStr(argbuf))
                FloorBeingSearched = extract_int(argbuf, 0);
 
        if (CtdlAccessCheck(ac_logged_in)) return;
@@ -623,13 +656,13 @@ void cmd_lprm_backend(struct ctdlroom *qrbuf, void *data)
                && ((qrbuf->QRflags & QR_MAILBOX) == 0)
            && ((qrbuf->QRfloor == (FloorBeingSearched))
                || ((FloorBeingSearched) < 0)))
-               list_roomname(qrbuf, ra, view);
+               list_roomname(qrbuf, ra, view, qrbuf->QRdefaultview);
 }
 
 void cmd_lprm(char *argbuf)
 {
        int FloorBeingSearched = (-1);
-       if (strlen(argbuf) > 0)
+       if (!IsEmptyStr(argbuf))
                FloorBeingSearched = extract_int(argbuf, 0);
 
        cprintf("%d Publiic rooms:\n", LISTING_FOLLOWS);
@@ -656,13 +689,13 @@ void cmd_lkrn_backend(struct ctdlroom *qrbuf, void *data)
            && (ra & UA_HASNEWMSGS)
            && ((qrbuf->QRfloor == (FloorBeingSearched))
                || ((FloorBeingSearched) < 0)))
-               list_roomname(qrbuf, ra, view);
+               list_roomname(qrbuf, ra, view, qrbuf->QRdefaultview);
 }
 
 void cmd_lkrn(char *argbuf)
 {
        int FloorBeingSearched = (-1);
-       if (strlen(argbuf) > 0)
+       if (!IsEmptyStr(argbuf))
                FloorBeingSearched = extract_int(argbuf, 0);
 
        if (CtdlAccessCheck(ac_logged_in)) return;
@@ -695,13 +728,13 @@ void cmd_lkro_backend(struct ctdlroom *qrbuf, void *data)
            && ((ra & UA_HASNEWMSGS) == 0)
            && ((qrbuf->QRfloor == (FloorBeingSearched))
                || ((FloorBeingSearched) < 0)))
-               list_roomname(qrbuf, ra, view);
+               list_roomname(qrbuf, ra, view, qrbuf->QRdefaultview);
 }
 
 void cmd_lkro(char *argbuf)
 {
        int FloorBeingSearched = (-1);
-       if (strlen(argbuf) > 0)
+       if (!IsEmptyStr(argbuf))
                FloorBeingSearched = extract_int(argbuf, 0);
 
        if (CtdlAccessCheck(ac_logged_in)) return;
@@ -734,13 +767,13 @@ void cmd_lzrm_backend(struct ctdlroom *qrbuf, void *data)
            && (ra & UA_ZAPPED)
            && ((qrbuf->QRfloor == (FloorBeingSearched))
                || ((FloorBeingSearched) < 0)))
-               list_roomname(qrbuf, ra, view);
+               list_roomname(qrbuf, ra, view, qrbuf->QRdefaultview);
 }
 
 void cmd_lzrm(char *argbuf)
 {
        int FloorBeingSearched = (-1);
-       if (strlen(argbuf) > 0)
+       if (!IsEmptyStr(argbuf))
                FloorBeingSearched = extract_int(argbuf, 0);
 
        if (CtdlAccessCheck(ac_logged_in)) return;
@@ -782,6 +815,7 @@ void usergoto(char *where, int display_result, int transiently,
        int s;
        char setstr[128], lostr[64], histr[64];
        long lo, hi;
+       int is_trash = 0;
 
        /* If the supplied room name is NULL, the caller wants us to know that
         * it has already copied the room record into CC->room, so
@@ -821,7 +855,6 @@ void usergoto(char *where, int display_result, int transiently,
                info = 1;
        }
 
-       get_mm();
         cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
         if (cdbfr != NULL) {
                msglist = (long *) cdbfr->ptr;
@@ -880,6 +913,10 @@ void usergoto(char *where, int display_result, int transiently,
                safestrncpy(truncated_roomname, &truncated_roomname[11], sizeof truncated_roomname);
        }
 
+       if (!strcasecmp(truncated_roomname, USERTRASHROOM)) {
+               is_trash = 1;
+       }
+
        if (retmsgs != NULL) *retmsgs = total_messages;
        if (retnew != NULL) *retnew = new_messages;
        lprintf(CTDL_DEBUG, "<%s> %d new of %d total messages\n",
@@ -890,7 +927,7 @@ void usergoto(char *where, int display_result, int transiently,
        CC->curr_view = (int)vbuf.v_view;
 
        if (display_result) {
-               cprintf("%d%c%s|%d|%d|%d|%d|%ld|%ld|%d|%d|%d|%d|%d|%d|\n",
+               cprintf("%d%c%s|%d|%d|%d|%d|%ld|%ld|%d|%d|%d|%d|%d|%d|%d|%d|\n",
                        CIT_OK, CtdlCheckExpress(),
                        truncated_roomname,
                        (int)new_messages,
@@ -904,12 +941,45 @@ void usergoto(char *where, int display_result, int transiently,
                        (int)newmailcount,
                        (int)CC->room.QRfloor,
                        (int)vbuf.v_view,
-                       (int)CC->room.QRdefaultview
+                       (int)CC->room.QRdefaultview,
+                       (int)is_trash,
+                       (int)CC->room.QRflags2
                );
        }
 }
 
 
+/*
+ * Handle some of the macro named rooms
+ */
+void convert_room_name_macros(char *towhere, size_t maxlen) {
+       if (!strcasecmp(towhere, "_BASEROOM_")) {
+               safestrncpy(towhere, config.c_baseroom, maxlen);
+       }
+       else if (!strcasecmp(towhere, "_MAIL_")) {
+               safestrncpy(towhere, MAILROOM, maxlen);
+       }
+       else if (!strcasecmp(towhere, "_TRASH_")) {
+               safestrncpy(towhere, USERTRASHROOM, maxlen);
+       }
+       else if (!strcasecmp(towhere, "_BITBUCKET_")) {
+               safestrncpy(towhere, config.c_twitroom, maxlen);
+       }
+       else if (!strcasecmp(towhere, "_CALENDAR_")) {
+               safestrncpy(towhere, USERCALENDARROOM, maxlen);
+       }
+       else if (!strcasecmp(towhere, "_TASKS_")) {
+               safestrncpy(towhere, USERTASKSROOM, maxlen);
+       }
+       else if (!strcasecmp(towhere, "_CONTACTS_")) {
+               safestrncpy(towhere, USERCONTACTSROOM, maxlen);
+       }
+       else if (!strcasecmp(towhere, "_NOTES_")) {
+               safestrncpy(towhere, USERNOTESROOM, maxlen);
+       }
+}
+
+
 /* 
  * cmd_goto()  -  goto a new room
  */
@@ -935,27 +1005,7 @@ void cmd_goto(char *gargs)
        /*
         * Handle some of the macro named rooms
         */
-       if (!strcasecmp(towhere, "_BASEROOM_")) {
-               safestrncpy(towhere, config.c_baseroom, sizeof towhere);
-       }
-       else if (!strcasecmp(towhere, "_MAIL_")) {
-               safestrncpy(towhere, MAILROOM, sizeof towhere);
-       }
-       else if (!strcasecmp(towhere, "_BITBUCKET_")) {
-               safestrncpy(towhere, config.c_twitroom, sizeof towhere);
-       }
-       else if (!strcasecmp(towhere, "_CALENDAR_")) {
-               safestrncpy(towhere, USERCALENDARROOM, sizeof towhere);
-       }
-       else if (!strcasecmp(towhere, "_TASKS_")) {
-               safestrncpy(towhere, USERTASKSROOM, sizeof towhere);
-       }
-       else if (!strcasecmp(towhere, "_CONTACTS_")) {
-               safestrncpy(towhere, USERCONTACTSROOM, sizeof towhere);
-       }
-       else if (!strcasecmp(towhere, "_NOTES_")) {
-               safestrncpy(towhere, USERNOTESROOM, sizeof towhere);
-       }
+       convert_room_name_macros(towhere, sizeof towhere);
 
        /* First try a regular match */
        c = getroom(&QRscratch, towhere);
@@ -1029,23 +1079,6 @@ void cmd_whok(void)
        struct cdbdata *cdbus;
        int ra;
 
-       getuser(&CC->user, CC->curr_user);
-
-       /*
-        * This command is only allowed by aides, room aides,
-        * and room namespace owners
-        */
-       if (is_room_aide()
-          || (atol(CC->room.QRname) == CC->user.usernum) ) {
-               /* access granted */
-       }
-       else {
-               /* access denied */
-                cprintf("%d Higher access or room ownership required.\n",
-                        ERROR + HIGHER_ACCESS_REQUIRED);
-                return;
-        }
-
        cprintf("%d Who knows room:\n", LISTING_FOLLOWS);
        cdb_rewind(CDB_USERS);
        while (cdbus = cdb_next_item(CDB_USERS), cdbus != NULL) {
@@ -1076,7 +1109,7 @@ void cmd_rdir(void)
        char tempfilename[PATH_MAX];
 
        if (CtdlAccessCheck(ac_logged_in)) return;
-       tmpnam(tempfilename);
+       CtdlMakeTempFileName(tempfilename, sizeof tempfilename);
        
        getroom(&CC->room, CC->room.QRname);
        getuser(&CC->user, CC->curr_user);
@@ -1091,32 +1124,23 @@ void cmd_rdir(void)
                cprintf("%d not here.\n", ERROR + HIGHER_ACCESS_REQUIRED);
                return;
        }
-       cprintf("%d %s|"
-#ifndef HAVE_DATA_DIR
-                       "."
-#else
-                       DATA_DIR
-#endif
-                       "/files/%s\n",
-                       LISTING_FOLLOWS, config.c_fqdn, CC->room.QRdirname);
+       cprintf("%d %s|%s/%s\n",
+                       LISTING_FOLLOWS, 
+                       config.c_fqdn,
+                       ctdl_file_dir, 
+                       CC->room.QRdirname);
 
-       snprintf(buf, sizeof buf, "ls "
-#ifndef HAVE_DATA_DIR
-                        "."
-#else
-                        DATA_DIR
-#endif
-                        "/files/%s  >%s 2> /dev/null",
-                        CC->room.QRdirname, tempfilename);
+       snprintf(buf, sizeof buf, 
+                        "ls %s/%s >%s 2>/dev/null",
+                        ctdl_file_dir,
+                        CC->room.QRdirname, 
+                        tempfilename);
        system(buf);
 
        snprintf(buf, sizeof buf, 
-#ifndef HAVE_DATA_DIR
-                        "."
-#else
-                        DATA_DIR
-#endif
-                        "/files/%s/filedir", CC->room.QRdirname);
+                        "%s/%s/filedir",
+                        ctdl_file_dir,
+                        CC->room.QRdirname);
        fd = fopen(buf, "r");
        if (fd == NULL)
                fd = fopen("/dev/null", "r");
@@ -1126,18 +1150,15 @@ void cmd_rdir(void)
                flnm[strlen(flnm) - 1] = 0;
                if (strcasecmp(flnm, "filedir")) {
                        snprintf(buf, sizeof buf, 
-#ifndef HAVE_DATA_DIR
-                                        "."
-#else
-                                        DATA_DIR
-#endif
-                                        "/files/%s/%s",
-                                        CC->room.QRdirname, flnm);
+                                        "%s/%s/%s",
+                                        ctdl_file_dir,
+                                        CC->room.QRdirname,
+                                        flnm);
                        stat(buf, &statbuf);
                        safestrncpy(comment, "", sizeof comment);
                        fseek(fd, 0L, 0);
                        while ((fgets(buf, sizeof buf, fd) != NULL)
-                              && (strlen(comment) == 0)) {
+                              && (IsEmptyStr(comment))) {
                                buf[strlen(buf) - 1] = 0;
                                if ((!strncasecmp(buf, flnm, strlen(flnm)))
                                    && (buf[strlen(flnm)] == ' '))
@@ -1225,7 +1246,7 @@ int CtdlRenameRoom(char *old_name, char *new_name, int new_floor) {
                ret = crr_room_not_found;
        }
 
-       else if ( (CC->user.axlevel < 6)
+       else if ( (CC->user.axlevel < 6) && (!CC->internal_pgm)
                  && (CC->user.usernum != qrbuf.QRroomaide)
                  && ( (((qrbuf.QRflags & QR_MAILBOX) == 0) || (atol(qrbuf.QRname) != CC->user.usernum))) )  {
                ret = crr_access_denied;
@@ -1438,17 +1459,14 @@ void cmd_setr(char *args)
 
        /* Create a room directory if necessary */
        if (CC->room.QRflags & QR_DIRECTORY) {
-               snprintf(buf, sizeof buf, 
-#ifndef HAVE_DATA_DIR
-                                "."
-#else
-                                DATA_DIR
-#endif
-                                "/files/%s", CC->room.QRdirname);
+               snprintf(buf, sizeof buf,"%s/%s",
+                                ctdl_file_dir,
+                                CC->room.QRdirname);
                mkdir(buf, 0755);
        }
-       snprintf(buf, sizeof buf, "%s> edited by %s\n", CC->room.QRname, CC->curr_user);
-       aide_message(buf);
+       snprintf(buf, sizeof buf, "The room \"%s\" has been edited by %s.\n",
+               CC->room.QRname, CC->curr_user);
+       aide_message(buf, "Room modification Message");
        cprintf("%d Ok\n", CIT_OK);
 }
 
@@ -1502,28 +1520,19 @@ void cmd_seta(char *new_ra)
         * the room table, otherwise it would deadlock!
         */
        if (post_notice == 1) {
-               if (strlen(usbuf.fullname) > 0)
+               if (!IsEmptyStr(usbuf.fullname))
                        snprintf(buf, sizeof buf,
-                               "%s is now room aide for %s>\n",
+                               "%s is now the room aide for \"%s\".\n",
                                usbuf.fullname, CC->room.QRname);
                else
                        snprintf(buf, sizeof buf,
-                               "There is now no room aide for %s>\n",
+                               "There is now no room aide for \"%s\".\n",
                                CC->room.QRname);
-               aide_message(buf);
+               aide_message(buf, "Aide Room Modification");
        }
        cprintf("%d Ok\n", CIT_OK);
 }
 
-/*
- * Generate an associated file name for a room
- */
-void assoc_file_name(char *buf, size_t n,
-                    struct ctdlroom *qrbuf, const char *prefix)
-{
-       snprintf(buf, n, "./%s/%ld", prefix, qrbuf->QRnumber);
-}
-
 /* 
  * retrieve info file for this room
  */
@@ -1533,7 +1542,7 @@ void cmd_rinf(void)
        char buf[SIZ];
        FILE *info_fp;
 
-       assoc_file_name(filename, sizeof filename, &CC->room, "info");
+       assoc_file_name(filename, sizeof filename, &CC->room, ctdl_info_dir);
        info_fp = fopen(filename, "r");
 
        if (info_fp == NULL) {
@@ -1542,7 +1551,7 @@ void cmd_rinf(void)
        }
        cprintf("%d Info:\n", LISTING_FOLLOWS);
        while (fgets(buf, sizeof buf, info_fp) != NULL) {
-               if (strlen(buf) > 0)
+               if (!IsEmptyStr(buf))
                        buf[strlen(buf) - 1] = 0;
                cprintf("%s\n", buf);
        }
@@ -1596,25 +1605,26 @@ void delete_room(struct ctdlroom *qrbuf)
 {
        struct floor flbuf;
        char filename[100];
+       /* TODO: filename magic? does this realy work? */
 
        lprintf(CTDL_NOTICE, "Deleting room <%s>\n", qrbuf->QRname);
 
        /* Delete the info file */
-       assoc_file_name(filename, sizeof filename, qrbuf, "info");
+       assoc_file_name(filename, sizeof filename, qrbuf, ctdl_info_dir);
        unlink(filename);
 
        /* Delete the image file */
-       assoc_file_name(filename, sizeof filename, qrbuf, "images");
+       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, "netconfigs");
+       assoc_file_name(filename, sizeof filename, qrbuf, ctdl_netcfg_dir);
        unlink(filename);
 
        /* Delete the messages in the room
         * (Careful: this opens an S_ROOMS critical section!)
         */
-       CtdlDeleteMessages(qrbuf->QRname, 0L, "", 0);
+       CtdlDeleteMessages(qrbuf->QRname, NULL, 0, "");
 
        /* Flag the room record as not in use */
        lgetroom(qrbuf, qrbuf->QRname);
@@ -1657,7 +1667,7 @@ int CtdlDoIHavePermissionToDeleteThisRoom(struct ctdlroom *qr) {
                }
 
                /* Can't delete your Mail> room */
-               if (!strcasecmp(&qr->QRname[12], MAILROOM)) return(0);
+               if (!strcasecmp(&qr->QRname[11], MAILROOM)) return(0);
 
                /* Otherwise it's ok */
                return(1);
@@ -1699,9 +1709,9 @@ void cmd_kill(char *argbuf)
                usergoto(config.c_baseroom, 0, 0, NULL, NULL);
 
                /* tell the world what we did */
-               snprintf(msg, sizeof msg, "%s> killed by %s\n",
+               snprintf(msg, sizeof msg, "The room \"%s\" has been deleted by %s.\n",
                         deleted_room_name, CC->curr_user);
-               aide_message(msg);
+               aide_message(msg, "Room Purger Message");
                cprintf("%d '%s' deleted.\n", CIT_OK, deleted_room_name);
        } else {
                cprintf("%d ok to delete.\n", CIT_OK);
@@ -1745,8 +1755,10 @@ unsigned create_room(char *new_room_name,
                qrbuf.QRflags = (qrbuf.QRflags | QR_GUESSNAME);
        if (new_room_type == 2)
                qrbuf.QRflags = (qrbuf.QRflags | QR_PASSWORDED);
-       if ( (new_room_type == 4) || (new_room_type == 5) )
+       if ( (new_room_type == 4) || (new_room_type == 5) ) {
                qrbuf.QRflags = (qrbuf.QRflags | QR_MAILBOX);
+               /* qrbuf.QRflags2 |= QR2_SUBJECTREQ; */
+       }
 
        /* If the user is requesting a personal room, set up the room
         * name accordingly (prepend the user number)
@@ -1791,13 +1803,11 @@ unsigned create_room(char *new_room_name,
        /* Grant the creator access to the room unless the avoid_access
         * parameter was specified.
         */
-       if (avoid_access == 0) {
-               lgetuser(&CC->user, CC->curr_user);
+       if ( (CC->logged_in) && (avoid_access == 0) ) {
                CtdlGetRelationship(&vbuf, &CC->user, &qrbuf);
                vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
                vbuf.v_flags = vbuf.v_flags | V_ACCESS;
                CtdlSetRelationship(&vbuf, &CC->user, &qrbuf);
-               lputuser(&CC->user);
        }
 
        /* resume our happy day */
@@ -1831,7 +1841,7 @@ void cmd_cre8(char *args)
        new_room_pass[9] = 0;
        new_room_floor = 0;
 
-       if ((strlen(new_room_name) == 0) && (cre8_ok == 1)) {
+       if ((IsEmptyStr(new_room_name)) && (cre8_ok == 1)) {
                cprintf("%d Invalid room name.\n", ERROR + ILLEGAL_VALUE);
                return;
        }
@@ -1860,13 +1870,13 @@ void cmd_cre8(char *args)
 
        if (CtdlAccessCheck(ac_logged_in)) return;
 
-       if (CC->user.axlevel < config.c_createax) {
+       if (CC->user.axlevel < config.c_createax || CC->internal_pgm) {
                cprintf("%d You need higher access to create rooms.\n",
                        ERROR + HIGHER_ACCESS_REQUIRED);
                return;
        }
 
-       if ((strlen(new_room_name) == 0) && (cre8_ok == 0)) {
+       if ((IsEmptyStr(new_room_name)) && (cre8_ok == 0)) {
                cprintf("%d Ok to create rooms.\n", CIT_OK);
                return;
        }
@@ -1908,7 +1918,7 @@ void cmd_cre8(char *args)
        /* post a message in Aide> describing the new room */
        notification_message = malloc(1024);
        snprintf(notification_message, 1024,
-               "%s> created by %s%s%s%s%s%s\n",
+               "A new room called \"%s\" has been created by %s%s%s%s%s%s\n",
                new_room_name,
                CC->user.fullname,
                ((newflags & QR_MAILBOX) ? " [personal]" : ""),
@@ -1917,7 +1927,7 @@ void cmd_cre8(char *args)
                ((newflags & QR_PASSWORDED) ? " Password: " : ""),
                ((newflags & QR_PASSWORDED) ? new_room_pass : "")
        );
-       aide_message(notification_message);
+       aide_message(notification_message, "Room Creation Message");
        free(notification_message);
 
        cprintf("%d '%s' has been created.\n", CIT_OK, new_room_name);
@@ -1939,7 +1949,7 @@ void cmd_einf(char *ok)
                cprintf("%d Ok.\n", CIT_OK);
                return;
        }
-       assoc_file_name(infofilename, sizeof infofilename, &CC->room, "info");
+       assoc_file_name(infofilename, sizeof infofilename, &CC->room, ctdl_info_dir);
        lprintf(CTDL_DEBUG, "opening\n");
        fp = fopen(infofilename, "w");
        lprintf(CTDL_DEBUG, "checking\n");
@@ -2006,7 +2016,7 @@ void cmd_cflr(char *argbuf)
 
        if (CtdlAccessCheck(ac_aide)) return;
 
-       if (strlen(new_floor_name) == 0) {
+       if (IsEmptyStr(new_floor_name)) {
                cprintf("%d Blank floor name not allowed.\n",
                        ERROR + ILLEGAL_VALUE);
                return;