/* $Id$ */
+#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <string.h>
+#ifdef HAVE_PTHREAD_H
#include <pthread.h>
+#endif
#include <time.h>
#include <limits.h>
+#include <errno.h>
#include "citadel.h"
#include "server.h"
#include "database.h"
#include "msgbase.h"
#include "serv_chat.h"
#include "citserver.h"
+#include "control.h"
+#include "tools.h"
/*
* Generic routine for determining user access to rooms
return(retval);
}
+/*
+ * Self-checking stuff for a room record read into memory
+ */
+void room_sanity_check(struct quickroom *qrbuf) {
+ /* Mailbox rooms are always on the lowest floor */
+ if (qrbuf->QRflags & QR_MAILBOX) {
+ qrbuf->QRfloor = 0;
+ }
+
+ /* Listing order of 0 is illegal except for base rooms */
+ if (qrbuf->QRorder == 0)
+ if (!is_noneditable(qrbuf))
+ qrbuf->QRorder = 64;
+ }
+
+
/*
* getroom() - retrieve room data from disk
*/
sizeof(struct quickroom) : cdbqr->len) );
cdb_free(cdbqr);
- /* Mailbox rooms are always on the lowest floor */
- if (qrbuf->QRflags & QR_MAILBOX) {
- qrbuf->QRfloor = 0;
- }
+ room_sanity_check(qrbuf);
return(0);
}
( (cdbqr->len > sizeof(struct quickroom)) ?
sizeof(struct quickroom) : cdbqr->len) );
cdb_free(cdbqr);
+ room_sanity_check(&qrbuf);
if (qrbuf.QRflags & QR_INUSE) (*CallBack)(&qrbuf);
}
}
-/*
- * Create a database key for storage of message lists
- */
-void msglist_key(char *dbkey, struct quickroom *whichroom) {
- int a;
-
- sprintf(dbkey, "%s%ld", whichroom->QRname, whichroom->QRgen);
- for (a=0; a<strlen(dbkey); ++a) dbkey[a]=tolower(dbkey[a]);
- }
-
/*
* get_msglist() - retrieve room message pointers
*/
void get_msglist(struct quickroom *whichroom) {
struct cdbdata *cdbfr;
- char dbkey[256];
- msglist_key(dbkey, whichroom);
-
if (CC->msglist != NULL) {
- free(CC->msglist);
+ phree(CC->msglist);
}
CC->msglist = NULL;
CC->num_msgs = 0;
- cdbfr = cdb_fetch(CDB_MSGLISTS, dbkey, strlen(dbkey));
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &whichroom->QRnumber, sizeof(long));
if (cdbfr == NULL) {
return;
}
- CC->msglist = malloc(cdbfr->len);
+ CC->msglist = mallok(cdbfr->len);
memcpy(CC->msglist, cdbfr->ptr, cdbfr->len);
CC->num_msgs = cdbfr->len / sizeof(long);
cdb_free(cdbfr);
* put_msglist() - retrieve room message pointers
*/
void put_msglist(struct quickroom *whichroom) {
- char dbkey[256];
- msglist_key(dbkey, whichroom);
- cdb_store(CDB_MSGLISTS, dbkey, strlen(dbkey),
- CC->msglist, CC->num_msgs * sizeof(long));
+ if (CC->msglist != NULL)
+ cdb_store(CDB_MSGLISTS, &whichroom->QRnumber, sizeof(long),
+ CC->msglist, CC->num_msgs * sizeof(long));
}
* like "gdbm: illegal data" (no big deal, but could use fixing).
*/
void delete_msglist(struct quickroom *whichroom) {
- char dbkey[256];
- msglist_key(dbkey, whichroom);
- cdb_delete(CDB_MSGLISTS, dbkey, strlen(dbkey));
+ cdb_delete(CDB_MSGLISTS, &whichroom->QRnumber, sizeof(long));
}
* So, why doesn't this function use the get_msglist() and put_msglist() stuff
* defined above? Because the room the message number is being written to
* may not be the current room (as is the case with cmd_move() for example).
+ *
+ * This function returns the highest message number present in the room after
+ * the add operation is performed - which is not necessarily the message
+ * being added.
*/
-void AddMessageToRoom(struct quickroom *whichroom, long newmsgid) {
- char dbkey[256];
+long AddMessageToRoom(struct quickroom *whichroom, long newmsgid) {
struct cdbdata *cdbfr;
int num_msgs;
long *msglist;
-
- msglist_key(dbkey, whichroom);
- cdbfr = cdb_fetch(CDB_MSGLISTS, dbkey, strlen(dbkey));
+ long highest_msg = 0L;
+
+ lprintf(9, "AddMessageToRoom(%s, %ld)\n", whichroom->QRname, newmsgid);
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &whichroom->QRnumber, sizeof(long));
if (cdbfr == NULL) {
msglist = NULL;
num_msgs = 0;
}
else {
- msglist = malloc(cdbfr->len);
+ msglist = mallok(cdbfr->len);
+ if (msglist==NULL) lprintf(3, "ERROR malloc msglist!\n");
num_msgs = cdbfr->len / sizeof(long);
memcpy(msglist, cdbfr->ptr, cdbfr->len);
cdb_free(cdbfr);
/* Now add the new message */
++num_msgs;
- msglist = realloc(msglist,
+ msglist = reallok(msglist,
(num_msgs * sizeof(long)) );
if (msglist == NULL) {
msglist[num_msgs - 1] = newmsgid;
+ /* Sort the message list, so all the msgid's are in order */
+ num_msgs = sort_msglist(msglist, num_msgs);
+
+ /* Determine the highest message number */
+ highest_msg = msglist[num_msgs - 1];
+
/* Write it back to disk. */
- cdb_store(CDB_MSGLISTS, dbkey, strlen(dbkey),
+ cdb_store(CDB_MSGLISTS, &whichroom->QRnumber, sizeof(long),
msglist, num_msgs * sizeof(long));
/* And finally, free up the memory we used. */
- free(msglist);
+ phree(msglist);
+ return(highest_msg);
}
}
/* ...and now the other parameters */
- cprintf("|%u|%d\n",
- qrbuf->QRflags,qrbuf->QRfloor);
+ cprintf("|%u|%d|%d\n",
+ qrbuf->QRflags,
+ (int)qrbuf->QRfloor,
+ (int)qrbuf->QRorder);
}
strcpy(CC->quickroom.QRname, where);
getroom(&CC->quickroom, where);
+
lgetuser(&CC->usersupp,CC->curr_user);
CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
- vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
- vbuf.v_flags = vbuf.v_flags | V_ACCESS;
+ /* Know the room ... but not if it's the page log room */
+ if (strcasecmp(where, config.c_logpages)) {
+ vbuf.v_flags = vbuf.v_flags & ~V_FORGET & ~V_LOCKOUT;
+ vbuf.v_flags = vbuf.v_flags | V_ACCESS;
+ }
CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
lputuser(&CC->usersupp,CC->curr_user);
ERROR+PASSWORD_REQUIRED);
return;
}
+ else if ( (QRscratch.QRflags&QR_PRIVATE) &&
+ ((QRscratch.QRflags&QR_PASSWORDED)==0) &&
+ ((QRscratch.QRflags&QR_GUESSNAME)==0) &&
+ ((ra & UA_KNOWN) == 0) ) {
+ goto NOPE;
+ }
else {
usergoto(towhere, 1);
return;
}
}
- cprintf("%d room '%s' not found\n",ERROR+ROOM_NOT_FOUND,towhere);
+NOPE: cprintf("%d room '%s' not found\n",ERROR+ROOM_NOT_FOUND,towhere);
}
}
getroom(&CC->quickroom, CC->quickroom.QRname);
- cprintf("%d%c%s|%s|%s|%d|%d\n",
+ cprintf("%d%c%s|%s|%s|%d|%d|%d\n",
OK,check_express(),
CC->quickroom.QRname,
((CC->quickroom.QRflags & QR_PASSWORDED) ? CC->quickroom.QRpasswd : ""),
((CC->quickroom.QRflags & QR_DIRECTORY) ? CC->quickroom.QRdirname : ""),
CC->quickroom.QRflags,
- (int)CC->quickroom.QRfloor);
+ (int)CC->quickroom.QRfloor,
+ (int)CC->quickroom.QRorder);
}
struct floor flbuf;
char old_name[ROOMNAMELEN];
int old_floor;
+ int new_order = 0;
if (!(CC->logged_in)) {
cprintf("%d Not logged in.\n",ERROR+NOT_LOGGED_IN);
}
}
+ if (num_parms(args)>=7) {
+ new_order = extract_int(args, 6);
+ if (new_order < 1) new_order = 1;
+ if (new_order > 127) new_order = 127;
+ }
+
lgetroom(&CC->quickroom, CC->quickroom.QRname);
strcpy(old_name, CC->quickroom.QRname);
extract(buf,args,0); buf[ROOMNAMELEN]=0;
extract(buf,args,2); buf[15]=0;
strncpy(CC->quickroom.QRdirname,buf,19);
CC->quickroom.QRflags = ( extract_int(args,3) | QR_INUSE);
+ if (num_parms(args)>=7)
+ CC->quickroom.QRorder = (char)new_order;
/* Clean up a client boo-boo: if the client set the room to
* guess-name or passworded, ensure that the private flag is
/* If the room name changed, then there are now two room records,
* so we have to delete the old one.
*/
- /* FIX - This causes everybody to think it's a new room, because the
- * visit structs no longer match! Major problem! We have to
- * assign each room a unique Object ID and index by that.
- */
if (strcasecmp(CC->quickroom.QRname, old_name)) {
putroom(NULL, old_name);
}
* Generate an associated file name for a room
*/
void assoc_file_name(char *buf, struct quickroom *qrbuf, char *prefix) {
- int a;
-
- sprintf(buf, "./prefix/%s.%ld", qrbuf->QRname, qrbuf->QRgen);
- for (a=0; a<strlen(buf); ++a) {
- if (buf[a]==32) buf[a]='.';
- }
+ sprintf(buf, "./%s/%ld", prefix, qrbuf->QRnumber);
}
/*
cdb_delete(CDB_MSGMAIN, &MsgToDelete, sizeof(long));
}
put_msglist(qrbuf);
- free(CC->msglist);
+ phree(CC->msglist);
CC->msglist = NULL;
CC->num_msgs = 0;
delete_msglist(qrbuf);
strncpy(qrbuf.QRname,new_room_name,ROOMNAMELEN);
strncpy(qrbuf.QRpasswd,new_room_pass,9);
qrbuf.QRflags = QR_INUSE;
+ qrbuf.QRnumber = get_new_room_number();
if (new_room_type > 0) qrbuf.QRflags=(qrbuf.QRflags|QR_PRIVATE);
if (new_room_type == 1) qrbuf.QRflags=(qrbuf.QRflags|QR_GUESSNAME);
if (new_room_type == 2) qrbuf.QRflags=(qrbuf.QRflags|QR_PASSWORDED);
return;
}
+ if (!strcasecmp(new_room_name, MAILROOM)) {
+ cprintf("%d '%s' already exists.\n",
+ ERROR+ALREADY_EXISTS, new_room_name);
+ return;
+ }
+
if (num_parms(args)>=5) {
getfloor(&flbuf,extract_int(args,4));
if ((flbuf.f_flags & F_INUSE) == 0) {
return;
}
- if (CC->usersupp.axlevel<3) {
+ if (CC->usersupp.axlevel < config.c_createax) {
cprintf("%d You need higher access to create rooms.\n",
ERROR+HIGHER_ACCESS_REQUIRED);
return;
/* Check to make sure the requested room name doesn't already exist */
if (getroom(&qrbuf, new_room_name)==0) {
cprintf("%d '%s' already exists.\n",
- ERROR,qrbuf.QRname);
+ ERROR+ALREADY_EXISTS, qrbuf.QRname);
return;
}
void cmd_einf(char *ok)
{ /* enter info file for current room */
FILE *fp;
- char infofilename[64];
+ char infofilename[256];
char buf[256];
if (!(CC->logged_in)) {
return;
}
- cprintf("%d Send info...\n",SEND_LISTING);
-
assoc_file_name(infofilename, &CC->quickroom, "info");
+ lprintf(9, "opening\n");
+ fp = fopen(infofilename, "w");
+ lprintf(9, "checking\n");
+ if (fp == NULL) {
+ cprintf("%d Cannot open %s: %s\n",
+ ERROR+INTERNAL_ERROR, infofilename, strerror(errno));
+ return;
+ }
+
+ cprintf("%d Send info...\n", SEND_LISTING);
- fp=fopen(infofilename,"w");
do {
client_gets(buf);
if (strcmp(buf,"000")) fprintf(fp,"%s\n",buf);