From ec3a0d835a49bd6813d86245c5ff5257df89ae8f Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Tue, 14 Sep 2010 09:50:32 -0400 Subject: [PATCH] CtdlRoomAccess() can now return a new value UA_REPLYALLOWED, which indicates that the user may post a message to this room *if* it is a reply to an existing message. CtdlDoIHavePermissionToPostInThisRoom() now must be told whether the user is replying to an existing message or posting a top-level message. If it is a reply, UA_REPLYALLOWED is checked. If it is a top-level message, UA_POSTALLOWED is checked. If UA_POSTALLOWED is not set, but UA_REPLYALLOWED is set, and the message is not a reply, a new error message indicates that the user may only reply to existing messages. I may add a new error code for this later. --- citadel/ipcdef.h | 15 ++++++++------- citadel/msgbase.c | 42 ++++++++++++++++++++++++++++++++---------- citadel/msgbase.h | 9 ++++++--- citadel/room_ops.c | 20 ++++++++++---------- 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/citadel/ipcdef.h b/citadel/ipcdef.h index a350069ba..f155a6e97 100644 --- a/citadel/ipcdef.h +++ b/citadel/ipcdef.h @@ -77,13 +77,14 @@ extern "C" { US_NOPROMPT | US_DISAPPEAR | US_PAGINATOR | \ US_FLOORS | US_COLOR | US_PROMPTCTL | US_EXTEDIT) -#define UA_KNOWN 2 -#define UA_GOTOALLOWED 4 -#define UA_HASNEWMSGS 8 -#define UA_ZAPPED 16 -#define UA_POSTALLOWED 32 -#define UA_ADMINALLOWED 64 -#define UA_DELETEALLOWED 128 +#define UA_KNOWN 2 /* Room appears in a 'known rooms' list */ +#define UA_GOTOALLOWED 4 /* User may goto this room if specified by exact name */ +#define UA_HASNEWMSGS 8 /* Unread messages exist in this room */ +#define UA_ZAPPED 16 /* User has forgotten (zapped) this room */ +#define UA_POSTALLOWED 32 /* User may post top-level messages here */ +#define UA_ADMINALLOWED 64 /* Aide or Room Aide rights exist here */ +#define UA_DELETEALLOWED 128 /* User is allowed to delete messages from this room */ +#define UA_REPLYALLOWED 256 /* User is allowed to reply to existing messages here */ #ifdef __cplusplus } diff --git a/citadel/msgbase.c b/citadel/msgbase.c index a34530828..a2224a8b5 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -3599,10 +3599,13 @@ struct CtdlMessage *CtdlMakeMessage( * room. Returns a *CITADEL ERROR CODE* and puts a message in errmsgbuf, or * returns 0 on success. */ -int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, - size_t n, - const char* RemoteIdentifier, - int PostPublic) { +int CtdlDoIHavePermissionToPostInThisRoom( + char *errmsgbuf, + size_t n, + const char* RemoteIdentifier, + int PostPublic, + int is_reply +) { int ra; if (!(CC->logged_in) && @@ -3667,7 +3670,18 @@ int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, } CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL); - if (!(ra & UA_POSTALLOWED)) { + + if ( (!(ra & UA_POSTALLOWED)) && (ra & UA_REPLYALLOWED) && (!is_reply) ) { + /* + * To be thorough, we ought to check to see if the message they are + * replying to is actually a valid one in this room, but unless this + * actually becomes a problem we'll go with high performance instead. + */ + snprintf(errmsgbuf, n, "You may only reply to existing messages here."); + return (ERROR + HIGHER_ACCESS_REQUIRED); + } + + else if (!(ra & UA_POSTALLOWED)) { snprintf(errmsgbuf, n, "Higher access is required to post in this room."); return (ERROR + HIGHER_ACCESS_REQUIRED); } @@ -3827,10 +3841,12 @@ struct recptypes *validate_recipients(const char *supplied_recipients, CC->room = tempQR; /* Check permissions to send mail to this room */ - err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, - sizeof errmsg, - RemoteIdentifier, - Flags + err = CtdlDoIHavePermissionToPostInThisRoom( + errmsg, + sizeof errmsg, + RemoteIdentifier, + Flags, + 0 /* 0 = not a reply */ ); if (err) { @@ -4033,7 +4049,13 @@ void cmd_ent0(char *entargs) /* first check to make sure the request is valid. */ - err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, sizeof errmsg, NULL, POST_LOGGED_IN); + err = CtdlDoIHavePermissionToPostInThisRoom( + errmsg, + sizeof errmsg, + NULL, + POST_LOGGED_IN, + (!IsEmptyStr(references)) /* is this a reply? or a top-level post? */ + ); if (err) { cprintf("%d %s\n", err, errmsg); diff --git a/citadel/msgbase.h b/citadel/msgbase.h index 5bbd7aef6..039a8a1bb 100644 --- a/citadel/msgbase.h +++ b/citadel/msgbase.h @@ -186,10 +186,13 @@ enum { CHECK_EXISTANCE, POST_LMTP }; + int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, - size_t n, - const char* RemoteIdentifier, - int PostPublic); + size_t n, + const char* RemoteIdentifier, + int PostPublic, + int is_reply +); /* values for which_set */ diff --git a/citadel/room_ops.c b/citadel/room_ops.c index 68eeb3638..22e0cb2dd 100644 --- a/citadel/room_ops.c +++ b/citadel/room_ops.c @@ -65,7 +65,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 | UA_POSTALLOWED | UA_DELETEALLOWED); + retval = (UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED | UA_REPLYALLOWED); vbuf.v_view = 0; goto SKIP_EVERYTHING; } @@ -88,7 +88,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 >= AxAideU) { - retval = UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED; + retval = UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED | UA_REPLYALLOWED; } else { retval = 0; } @@ -130,11 +130,11 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, /* Also, mailbox owners can delete their messages */ if (roombuf->QRflags & QR_MAILBOX) { if (userbuf->usernum == atol(roombuf->QRname)) { - retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED; + retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED | UA_REPLYALLOWED; } /* An explicit match means the user belongs in this room */ if (vbuf.v_flags & V_ACCESS) { - retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED; + retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_DELETEALLOWED | UA_REPLYALLOWED; } } @@ -151,7 +151,7 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, if ((userbuf->axlevel < AxNetU) && (roombuf->QRflags & QR_NETWORK)) post_allowed = 0; if (roombuf->QRflags & QR_READONLY) post_allowed = 0; if (post_allowed) { - retval = retval | UA_POSTALLOWED; + retval = retval | UA_POSTALLOWED | UA_REPLYALLOWED; } /* If "collaborative deletion" is active for this room, any user who can post @@ -177,17 +177,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 & ~UA_POSTALLOWED; + retval = retval & ~UA_KNOWN & ~UA_GOTOALLOWED & ~UA_POSTALLOWED & ~UA_REPLYALLOWED; } /* Aides get access to all private rooms */ if ( (userbuf->axlevel >= AxAideU) && ((roombuf->QRflags & QR_MAILBOX) == 0) ) { if (vbuf.v_flags & V_FORGET) { - retval = retval | UA_GOTOALLOWED | UA_POSTALLOWED; + retval = retval | UA_GOTOALLOWED | UA_POSTALLOWED | UA_REPLYALLOWED; } else { - retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED; + retval = retval | UA_KNOWN | UA_GOTOALLOWED | UA_POSTALLOWED | UA_REPLYALLOWED; } } @@ -196,14 +196,14 @@ void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, */ if ( (userbuf->axlevel >= AxAideU) && (roombuf->QRflags & QR_MAILBOX) ) { - retval = retval | UA_GOTOALLOWED | UA_POSTALLOWED; + retval = retval | UA_GOTOALLOWED | UA_POSTALLOWED | UA_REPLYALLOWED; } /* Aides and Room Aides have admin privileges */ if ( (userbuf->axlevel >= AxAideU) || (userbuf->usernum == roombuf->QRroomaide) ) { - retval = retval | UA_ADMINALLOWED | UA_DELETEALLOWED | UA_POSTALLOWED; + retval = retval | UA_ADMINALLOWED | UA_DELETEALLOWED | UA_POSTALLOWED | UA_REPLYALLOWED; } NEWMSG: /* By the way, we also check for the presence of new messages */ -- 2.30.2