+
+void AddValidUser(struct ctdluser *usbuf, void *data) {
+ struct ValidUser *vuptr;
+
+ vuptr = (struct ValidUser *)malloc(sizeof(struct ValidUser));
+ vuptr->next = ValidUserList;
+ vuptr->vu_usernum = usbuf->usernum;
+ ValidUserList = vuptr;
+}
+
+void AddValidRoom(struct ctdlroom *qrbuf, void *data) {
+ struct ValidRoom *vrptr;
+
+ vrptr = (struct ValidRoom *)malloc(sizeof(struct ValidRoom));
+ vrptr->next = ValidRoomList;
+ vrptr->vr_roomnum = qrbuf->QRnumber;
+ vrptr->vr_roomgen = qrbuf->QRgen;
+ ValidRoomList = vrptr;
+}
+
+void DoPurgeRooms(struct ctdlroom *qrbuf, void *data) {
+ time_t age, purge_secs;
+ struct PurgeList *pptr;
+ struct ValidUser *vuptr;
+ int do_purge = 0;
+
+ /* For mailbox rooms, there's only one purging rule: if the user who
+ * owns the room still exists, we keep the room; otherwise, we purge
+ * it. Bypass any other rules.
+ */
+ if (qrbuf->QRflags & QR_MAILBOX) {
+ /* if user not found, do_purge will be 1 */
+ do_purge = 1;
+ for (vuptr=ValidUserList; vuptr!=NULL; vuptr=vuptr->next) {
+ if (vuptr->vu_usernum == atol(qrbuf->QRname)) {
+ do_purge = 0;
+ }
+ }
+ }
+ else {
+ /* Any of these attributes render a room non-purgable */
+ if (qrbuf->QRflags & QR_PERMANENT) return;
+ if (qrbuf->QRflags & QR_DIRECTORY) return;
+ if (qrbuf->QRflags & QR_NETWORK) return;
+ if (!strcasecmp(qrbuf->QRname, SYSCONFIGROOM)) return;
+ if (is_noneditable(qrbuf)) return;
+
+ /* If we don't know the modification date, be safe and don't purge */
+ if (qrbuf->QRmtime <= (time_t)0) return;
+
+ /* If no room purge time is set, be safe and don't purge */
+ if (config.c_roompurge < 0) return;
+
+ /* Otherwise, check the date of last modification */
+ age = time(NULL) - (qrbuf->QRmtime);
+ purge_secs = (time_t)config.c_roompurge * (time_t)86400;
+ if (purge_secs <= (time_t)0) return;
+ lprintf(CTDL_DEBUG, "<%s> is <%ld> seconds old\n", qrbuf->QRname, (long)age);
+ if (age > purge_secs) do_purge = 1;
+ } /* !QR_MAILBOX */
+
+ if (do_purge) {
+ pptr = (struct PurgeList *) malloc(sizeof(struct PurgeList));
+ pptr->next = RoomPurgeList;
+ strcpy(pptr->name, qrbuf->QRname);
+ RoomPurgeList = pptr;
+ }
+
+}
+
+
+
+int PurgeRooms(void) {
+ struct PurgeList *pptr;
+ int num_rooms_purged = 0;
+ struct ctdlroom qrbuf;
+ struct ValidUser *vuptr;
+ char *transcript = NULL;
+
+ lprintf(CTDL_DEBUG, "PurgeRooms() called\n");
+
+
+ /* Load up a table full of valid user numbers so we can delete
+ * user-owned rooms for users who no longer exist */
+ ForEachUser(AddValidUser, NULL);
+
+ /* Then cycle through the room file */
+ ForEachRoom(DoPurgeRooms, NULL);
+
+ /* Free the valid user list */
+ while (ValidUserList != NULL) {
+ vuptr = ValidUserList->next;
+ free(ValidUserList);
+ ValidUserList = vuptr;
+ }
+
+
+ transcript = malloc(SIZ);
+ strcpy(transcript, "The following rooms have been auto-purged:\n");
+
+ while (RoomPurgeList != NULL) {
+ if (getroom(&qrbuf, RoomPurgeList->name) == 0) {
+ transcript=realloc(transcript, strlen(transcript)+SIZ);
+ snprintf(&transcript[strlen(transcript)], SIZ, " %s\n",
+ qrbuf.QRname);
+ delete_room(&qrbuf);
+ }
+ pptr = RoomPurgeList->next;
+ free(RoomPurgeList);
+ RoomPurgeList = pptr;
+ ++num_rooms_purged;
+ }
+
+ if (num_rooms_purged > 0) aide_message(transcript, "Room Autopurger Message");
+ free(transcript);
+
+ lprintf(CTDL_DEBUG, "Purged %d rooms.\n", num_rooms_purged);
+ return(num_rooms_purged);
+}
+
+
+/*
+ * Back end function to check user accounts for associated Unix accounts
+ * which no longer exist. (Only relevant for host auth mode.)
+ */
+void do_uid_user_purge(struct ctdluser *us, void *data) {
+ struct PurgeList *pptr;
+
+ if ((us->uid != (-1)) && (us->uid != CTDLUID)) {
+ if (getpwuid(us->uid) == NULL) {
+ pptr = (struct PurgeList *)
+ malloc(sizeof(struct PurgeList));
+ pptr->next = UserPurgeList;
+ strcpy(pptr->name, us->fullname);
+ UserPurgeList = pptr;
+ }
+ }
+ else {
+ ++users_not_purged;
+ }
+}
+
+
+
+/*
+ * Back end function to check user accounts for expiration.
+ */
+void do_user_purge(struct ctdluser *us, void *data) {