START_CHAT_MODE is renamed to SEND_THEN_RECV
authorArt Cancro <ajc@citadel.org>
Mon, 8 Jan 2024 15:19:58 +0000 (10:19 -0500)
committerArt Cancro <ajc@citadel.org>
Mon, 8 Jan 2024 15:19:58 +0000 (10:19 -0500)
This protocol mode began almost 30 years ago when we handled real time chat by
holding a session open and moving data back and forth until told to stop.  We
don't do that anymore, but there are several places where a command requires
sending long data in both directions.  SEND_THEN_RECV is a better name for this.

citadel/server/ipcdef.h
citadel/server/modules/calendar/serv_calendar.c
citadel/server/modules/ctdlproto/serv_messages.c
libcitadel/lib/libcitadel.h
textclient/citadel_ipc.c
webcit/messages.c
webcit/webcit.h

index 6f6e9e1fa7b263914ba430be21a3b65f9b48b1bc..45043e661a02f7286618071291a46d37d04d1bd7 100644 (file)
@@ -5,7 +5,7 @@
 #define ERROR                  500
 #define BINARY_FOLLOWS         600
 #define SEND_BINARY            700
-#define START_CHAT_MODE                800
+#define SEND_THEN_RECV         800
 
 #define INTERNAL_ERROR         10
 #define TOO_BIG                        11
index 5e169c1b6a46ceb049bf9658f74bbf5a7b567108..6b05678a079c5215d9eb2c9f1d91153463599a57 100644 (file)
@@ -1711,74 +1711,6 @@ void ical_putics(void) {
 }
 
 
-// All Citadel calendar commands from the client come through here.
-void cmd_ical(char *argbuf) {
-       char subcmd[64];
-       long msgnum;
-       char partnum[256];
-       char action[256];
-       char who[256];
-
-       extract_token(subcmd, argbuf, 0, '|', sizeof subcmd);
-
-       // Allow "test" and "freebusy" subcommands without logging in.
-
-       if (!strcasecmp(subcmd, "test")) {
-               cprintf("%d This server supports calendaring\n", CIT_OK);
-               return;
-       }
-
-       if (!strcasecmp(subcmd, "freebusy")) {
-               extract_token(who, argbuf, 1, '|', sizeof who);
-               ical_freebusy(who);
-               return;
-       }
-
-       if (!strcasecmp(subcmd, "sgi")) {
-               CIT_ICAL->server_generated_invitations = (extract_int(argbuf, 1) ? 1 : 0) ;
-               cprintf("%d %d\n", CIT_OK, CIT_ICAL->server_generated_invitations);
-               return;
-       }
-
-       if (CtdlAccessCheck(ac_logged_in)) return;
-
-       if (!strcasecmp(subcmd, "respond")) {
-               msgnum = extract_long(argbuf, 1);
-               extract_token(partnum, argbuf, 2, '|', sizeof partnum);
-               extract_token(action, argbuf, 3, '|', sizeof action);
-               ical_respond(msgnum, partnum, action);
-               return;
-       }
-
-       if (!strcasecmp(subcmd, "handle_rsvp")) {
-               msgnum = extract_long(argbuf, 1);
-               extract_token(partnum, argbuf, 2, '|', sizeof partnum);
-               extract_token(action, argbuf, 3, '|', sizeof action);
-               ical_handle_rsvp(msgnum, partnum, action);
-               return;
-       }
-
-       if (!strcasecmp(subcmd, "conflicts")) {
-               msgnum = extract_long(argbuf, 1);
-               extract_token(partnum, argbuf, 2, '|', sizeof partnum);
-               ical_conflicts(msgnum, partnum);
-               return;
-       }
-
-       if (!strcasecmp(subcmd, "getics")) {
-               ical_getics();
-               return;
-       }
-
-       if (!strcasecmp(subcmd, "putics")) {
-               ical_putics();
-               return;
-       }
-
-       cprintf("%d Invalid subcommand\n", ERROR + CMD_NOT_SUPPORTED);
-}
-
-
 // We don't know if the calendar room exists so we just create it at login
 void ical_CtdlCreateRoom(void) {
        struct ctdlroom qr;
@@ -2394,6 +2326,88 @@ void ical_fixed_output(char *ptr, int len) {
 }
 
 
+// This is an experimental implementation of CALDAV REPORT operations (RFC 4791 section 7)
+// fundamentally handled in the Citadel Server.  A web implementation should be able to just
+// change the encapsulation to HTTP with the data format unchanged.
+void ical_report(void) {
+       cprintf("%d Hi from Citadel\n", CIT_OK);
+}
+
+
+// All Citadel calendar commands from the client come through here.
+void cmd_ical(char *argbuf) {
+       char subcmd[64];
+       long msgnum;
+       char partnum[256];
+       char action[256];
+       char who[256];
+
+       extract_token(subcmd, argbuf, 0, '|', sizeof subcmd);
+
+       // Allow "test" and "freebusy" and "sgi" subcommands without logging in.
+
+       if (!strcasecmp(subcmd, "test")) {
+               cprintf("%d This server supports calendaring\n", CIT_OK);
+               return;
+       }
+
+       if (!strcasecmp(subcmd, "freebusy")) {
+               extract_token(who, argbuf, 1, '|', sizeof who);
+               ical_freebusy(who);
+               return;
+       }
+
+       if (!strcasecmp(subcmd, "sgi")) {
+               CIT_ICAL->server_generated_invitations = (extract_int(argbuf, 1) ? 1 : 0) ;
+               cprintf("%d %d\n", CIT_OK, CIT_ICAL->server_generated_invitations);
+               return;
+       }
+
+       // All other commands require a user to be logged in.
+       if (CtdlAccessCheck(ac_logged_in)) return;
+
+       if (!strcasecmp(subcmd, "report")) {
+               ical_report();
+               return;
+       }
+
+       if (!strcasecmp(subcmd, "respond")) {
+               msgnum = extract_long(argbuf, 1);
+               extract_token(partnum, argbuf, 2, '|', sizeof partnum);
+               extract_token(action, argbuf, 3, '|', sizeof action);
+               ical_respond(msgnum, partnum, action);
+               return;
+       }
+
+       if (!strcasecmp(subcmd, "handle_rsvp")) {
+               msgnum = extract_long(argbuf, 1);
+               extract_token(partnum, argbuf, 2, '|', sizeof partnum);
+               extract_token(action, argbuf, 3, '|', sizeof action);
+               ical_handle_rsvp(msgnum, partnum, action);
+               return;
+       }
+
+       if (!strcasecmp(subcmd, "conflicts")) {
+               msgnum = extract_long(argbuf, 1);
+               extract_token(partnum, argbuf, 2, '|', sizeof partnum);
+               ical_conflicts(msgnum, partnum);
+               return;
+       }
+
+       if (!strcasecmp(subcmd, "getics")) {
+               ical_getics();
+               return;
+       }
+
+       if (!strcasecmp(subcmd, "putics")) {
+               ical_putics();
+               return;
+       }
+
+       cprintf("%d Invalid subcommand\n", ERROR + CMD_NOT_SUPPORTED);
+}
+
+
 // Initialization function, called from modules_init.c
 char *ctdl_module_init_calendar(void) {
        if (!threading) {
index 7e18c0bc994c5d367f53eda5f211d34520815413..9a85f263b716ac28c1b5685d73a58d9ea46b9e31 100644 (file)
@@ -26,7 +26,7 @@ void simple_listing(long msgnum, void *userdata) {
 // Back end for the MSGS command: output header summary.
 void headers_listing(long msgnum, void *userdata) {
        struct CtdlMessage *msg;
-       int output_mode =  *(int *)userdata;
+       int output_mode = *(int *)userdata;
 
        msg = CtdlFetchMessage(msgnum, 0);
        if (msg == NULL) {
@@ -149,7 +149,7 @@ void cmd_msgs(char *cmdbuf) {
        int cm_ref = 0;
        int with_template = 0;
        struct CtdlMessage *template = NULL;
-        msg_filter filt;
+       msg_filter filt;
        char search_string[1024];
        ForEachMsgCallback CallBack;
 
@@ -205,7 +205,7 @@ void cmd_msgs(char *cmdbuf) {
        if (with_template == 1) {
                memset(buf, 0, 5);
                unbuffer_output();
-               cprintf("%d Send template then receive message list\n", START_CHAT_MODE);
+               cprintf("%d Send template then receive message list\n", SEND_THEN_RECV);
                template = (struct CtdlMessage *) malloc(sizeof(struct CtdlMessage));
                memset(template, 0, sizeof(struct CtdlMessage));
                template->cm_magic = CTDLMESSAGE_MAGIC;
@@ -228,8 +228,7 @@ void cmd_msgs(char *cmdbuf) {
        else if (with_template == 2) {
                long i = 0;
                memset(buf, 0, 5);
-               cprintf("%d Send list of headers\n",
-                       START_CHAT_MODE);
+               cprintf("%d Send list of headers\n", SEND_THEN_RECV);
                filt.Filter = NewHash(1, lFlathash);
                filt.buffer = NewStrBufPlain(NULL, 1024);
                while(client_getln(buf, sizeof buf) >= 0 && strcmp(buf,"000")) {
@@ -249,22 +248,24 @@ void cmd_msgs(char *cmdbuf) {
 
        if (with_template < 2) {
                CtdlForEachMessage(mode,
-                                  ( (mode == MSGS_SEARCH) ? 0 : cm_ref ),
-                                  ( (mode == MSGS_SEARCH) ? search_string : NULL ),
-                                  NULL,
-                                  template,
-                                  CallBack,
-                                  &output_mode);
+                       ( (mode == MSGS_SEARCH) ? 0 : cm_ref ),
+                       ( (mode == MSGS_SEARCH) ? search_string : NULL ),
+                       NULL,
+                       template,
+                       CallBack,
+                       &output_mode
+               );
                if (template != NULL) CM_Free(template);
        }
        else {
                CtdlForEachMessage(mode,
-                                  ( (mode == MSGS_SEARCH) ? 0 : cm_ref ),
-                                  ( (mode == MSGS_SEARCH) ? search_string : NULL ),
-                                  NULL,
-                                  NULL,
-                                  CallBack,
-                                  &filt);
+                       ( (mode == MSGS_SEARCH) ? 0 : cm_ref ),
+                       ( (mode == MSGS_SEARCH) ? search_string : NULL ),
+                       NULL,
+                       NULL,
+                       CallBack,
+                       &filt
+               );
                DeleteHashPos(&filt.p);
                DeleteHash(&filt.Filter);
                FreeStrBuf(&filt.buffer);
@@ -420,9 +421,9 @@ void cmd_ent0(char *entargs) {
        if (IsEmptyStr(newusername)) {
                strcpy(newusername, CC->user.fullname);
        }
-       if (  (CC->user.axlevel < AxAideU)
-             && (strcasecmp(newusername, CC->user.fullname))
-             && (strcasecmp(newusername, CC->cs_inet_fn))
+       if (    (CC->user.axlevel < AxAideU)
+               && (strcasecmp(newusername, CC->user.fullname))
+               && (strcasecmp(newusername, CC->cs_inet_fn))
        ) {     
                cprintf("%d You don't have permission to author messages as '%s'.\n",
                        ERROR + HIGHER_ACCESS_REQUIRED,
@@ -527,10 +528,11 @@ void cmd_ent0(char *entargs) {
                        return;
                }
        
-               if ((RESTRICT_INTERNET == 1)
-                   && (valid_to->num_internet + valid_cc->num_internet + valid_bcc->num_internet > 0)
-                   && ((CC->user.flags & US_INTERNET) == 0)
-                   && (!CC->internal_pgm)) {
+               if (    (RESTRICT_INTERNET == 1)
+                       && (valid_to->num_internet + valid_cc->num_internet + valid_bcc->num_internet > 0)
+                       && ((CC->user.flags & US_INTERNET) == 0)
+                       && (!CC->internal_pgm)
+               ) {
                        cprintf("%d You don't have access to Internet mail.\n", ERROR + HIGHER_ACCESS_REQUIRED);
                        free_recipients(valid_to);
                        free_recipients(valid_cc);
@@ -582,17 +584,19 @@ void cmd_ent0(char *entargs) {
 
        // Read in the message from the client.
        if (do_confirm) {
-               cprintf("%d send message\n", START_CHAT_MODE);
+               cprintf("%d send message\n", SEND_THEN_RECV);
        }
        else {
                cprintf("%d send message\n", SEND_LISTING);
        }
 
-       msg = CtdlMakeMessage(&CC->user, recp, cc,
-                             CC->room.QRname, anonymous, format_type,
-                             newusername, newuseremail, subject,
-                             ((!IsEmptyStr(supplied_euid)) ? supplied_euid : NULL),
-                             NULL, references);
+       msg = CtdlMakeMessage(
+               &CC->user, recp, cc,
+               CC->room.QRname, anonymous, format_type,
+               newusername, newuseremail, subject,
+               ((!IsEmptyStr(supplied_euid)) ? supplied_euid : NULL),
+               NULL, references
+       );
 
        // Put together one big recipients struct containing to/cc/bcc all in one.  This is for the envelope.
        char *all_recps = malloc(SIZ * 3);
@@ -747,8 +751,11 @@ void cmd_move(char *args) {
        if (CC->user.usernum == CC->room.QRroomaide) permit = 1;
 
        // Permit move/copy from personal rooms
-       if ((CC->room.QRflags & QR_MAILBOX)
-           && (qtemp.QRflags & QR_MAILBOX)) permit = 1;
+       if (    (CC->room.QRflags & QR_MAILBOX)
+               && (qtemp.QRflags & QR_MAILBOX)
+       ) {
+               permit = 1;
+       }
 
        // Permit only copy from public to personal room
        if (    (is_copy)
@@ -762,11 +769,16 @@ void cmd_move(char *args) {
        if (CC->room.QRflags2 & QR2_COLLABDEL) permit = 1;
 
        // Users allowed to post into the target room may move into it too.
-       if ((CC->room.QRflags & QR_MAILBOX) && 
-           (qtemp.QRflags & UA_POSTALLOWED))  permit = 1;
+       if (    (CC->room.QRflags & QR_MAILBOX)
+               && (qtemp.QRflags & UA_POSTALLOWED)
+       ) {
+               permit = 1;
+       }
 
        // User must have access to target room
-       if (!(ra & UA_KNOWN))  permit = 0;
+       if (!(ra & UA_KNOWN)) {
+               permit = 0;
+       }
 
        if (!permit) {
                cprintf("%d Higher access required.\n", ERROR + HIGHER_ACCESS_REQUIRED);
index e2767345ad8c7c01c2d38c394bcc553f3b74b699..fd19bfaa17debff37e8f6a0d08aeca69815ee9a0 100644 (file)
@@ -692,7 +692,7 @@ extern "C" {
 #define ERROR                  500
 #define BINARY_FOLLOWS         600
 #define SEND_BINARY            700
-#define START_CHAT_MODE                800
+#define SEND_THEN_RECV         800
 
 #define INTERNAL_ERROR         10
 #define TOO_BIG                        11
index d5899c247fc5271c85fdf0486c2d9a7e5d925ea5..1a5164d7ff4dab0fcd7929b9c1dca2fac7992e7a 100644 (file)
@@ -2667,7 +2667,7 @@ int CtdlIPCGenericCommand(CtdlIPC * ipc,
                                ret = -ret;
                        }       /* else who knows?  DANGER WILL ROBINSON */
                        break;
-               case 8: /* START_CHAT_MODE */
+               case 8: /* SEND_THEN_RECV */
                        if (!strncasecmp(command, "CHAT", 4)) {
                                /* Don't call chatmode with generic! */
                                CtdlIPC_putline(ipc, "/quit");
index 69f3c5a83a4e26fcfab0e36b3f31c9fdd239aa09..f8da6aa73d06fe5a777069dee792438611ff450b 100644 (file)
@@ -305,7 +305,7 @@ long HttpStatus(long CitadelStatus) {
        default:
        case BINARY_FOLLOWS:
        case SEND_BINARY:
-       case START_CHAT_MODE:
+       case SEND_THEN_RECV:
        case ASYNC_MSG:
        case MORE_DATA:
        case SEND_LISTING:
index 5a56e09965c70ab9366ee0e008d0afaffd22710d..2963987011adddb8379eee173c7b0ec09243fe7b 100644 (file)
@@ -155,7 +155,7 @@ extern char *ssl_cipher_list;
 #define ERROR          500
 #define BINARY_FOLLOWS         600
 #define SEND_BINARY    700
-#define START_CHAT_MODE        800
+#define SEND_THEN_RECV 800
 #define ASYNC_MSG      900
 
 #define MINORCODE(a) (a % 100)