New server command DLAT (DownLoad ATtachment) which
authorArt Cancro <ajc@citadel.org>
Sat, 28 Oct 2006 16:05:12 +0000 (16:05 +0000)
committerArt Cancro <ajc@citadel.org>
Sat, 28 Oct 2006 16:05:12 +0000 (16:05 +0000)
is similar to OPNA (OPeN Attachment), except it outputs the
entire MIME part in a single server operation instead of
opening a download file for block transfer.  This will be useful
for grabbing small components such as calendar appointments and
address book entries with substantialy less overhead.

citadel/citserver.c
citadel/msgbase.c
citadel/msgbase.h
citadel/server.h
citadel/techdoc/protocol.txt

index e86b1e1bfcec12ff3ea038eee08b18e8700af111..95eab2fc673ceac0d2c6cf8a8d0b238effdedc88 100644 (file)
@@ -1077,6 +1077,10 @@ void do_command_loop(void) {
                cmd_opna(&cmdbuf[5]);
        }
 
+       else if (!strncasecmp(cmdbuf,"DLAT",4)) {
+               cmd_dlat(&cmdbuf[5]);
+       }
+
        else if (!strncasecmp(cmdbuf,"INFO",4)) {
                cmd_info();
        }
index 1a1f984f1aa6368ddf770f9307bbb0bb59443e97..2a6b775c8a0efa1e6e48058793796efcf5b6458c 100644 (file)
@@ -969,6 +969,27 @@ void mime_download(char *name, char *filename, char *partnum, char *disp,
 
 
 
+/*
+ * Callback function for mime parser that outputs a section all at once
+ */
+void mime_spew_section(char *name, char *filename, char *partnum, char *disp,
+                  void *content, char *cbtype, char *cbcharset, size_t length,
+                  char *encoding, void *cbuserdata)
+{
+       int *found_it = (int *)cbuserdata;
+
+       /* ...or if this is not the desired section */
+       if (strcasecmp(CC->download_desired_section, partnum))
+               return;
+
+       *found_it = 1;
+
+       cprintf("%d %d\n", BINARY_FOLLOWS, length);
+       client_write(content, length);
+}
+
+
+
 /*
  * Load a message from disk into memory.
  * This is used by CtdlOutputMsg() and other fetch functions.
@@ -1492,6 +1513,32 @@ int CtdlOutputPreLoadedMsg(
                return((CC->download_fp != NULL) ? om_ok : om_mime_error);
        }
 
+       /* MT_SPEW_SECTION is like MT_DOWNLOAD except it outputs the whole MIME part
+        * in a single server operation instead of opening a download file.
+        */
+       if (mode == MT_SPEW_SECTION) {
+               if (TheMessage->cm_format_type != FMT_RFC822) {
+                       if (do_proto)
+                               cprintf("%d This is not a MIME message.\n",
+                               ERROR + ILLEGAL_VALUE);
+               } else {
+                       /* Parse the message text component */
+                       int found_it = 0;
+
+                       mptr = TheMessage->cm_fields['M'];
+                       mime_parser(mptr, NULL, *mime_spew_section, NULL, NULL, (void *)&found_it, 0);
+                       /* If section wasn't found, print an error
+                        */
+                       if (!found_it) {
+                               if (do_proto) cprintf(
+                                       "%d Section %s not found.\n",
+                                       ERROR + FILE_NOT_FOUND,
+                                       CC->download_desired_section);
+                       }
+               }
+               return((CC->download_fp != NULL) ? om_ok : om_mime_error);
+       }
+
        /* now for the user-mode message reading loops */
        if (do_proto) cprintf("%d msg:\n", LISTING_FOLLOWS);
 
@@ -1911,6 +1958,23 @@ void cmd_opna(char *cmdbuf)
        CtdlOutputMsg(msgid, MT_DOWNLOAD, 0, 1, 1, NULL);
 }                      
 
+
+/*
+ * Open a component of a MIME message and transmit it all at once
+ */
+void cmd_dlat(char *cmdbuf)
+{
+       long msgid;
+       char desired_section[128];
+
+       msgid = extract_long(cmdbuf, 0);
+       extract_token(desired_section, cmdbuf, 1, '|', sizeof desired_section);
+       safestrncpy(CC->download_desired_section, desired_section,
+               sizeof CC->download_desired_section);
+       CtdlOutputMsg(msgid, MT_SPEW_SECTION, 0, 1, 1, NULL);
+}                      
+
+
 /*
  * Save one or more message pointers into a specified room
  * (Returns 0 for success, nonzero for failure)
index 4295d7be386566e4b0e54e430a1f73beb9635dc9..d06c6398a8fe310e513f89b9d5de0833e8d9a2e4 100644 (file)
@@ -91,6 +91,7 @@ void cmd_msg3 (char *cmdbuf);
 void cmd_msg4 (char *cmdbuf);
 void cmd_msgp (char *cmdbuf);
 void cmd_opna (char *cmdbuf);
+void cmd_dlat (char *cmdbuf);
 long send_message (struct CtdlMessage *);
 void loadtroom (void);
 long CtdlSubmitMsg(struct CtdlMessage *, struct recptypes *, char *);
index 8061e3df05cbacfdb0ef79ab88b24ed82d5b5984..e76fe1ac803c6dd15979a8c57867fb11f3ea4f84 100644 (file)
@@ -242,7 +242,8 @@ enum {
        MT_CITADEL,             /* Citadel proprietary */
        MT_RFC822,              /* RFC822 */
        MT_MIME,                /* MIME-formatted message */
-       MT_DOWNLOAD             /* Download a component */
+       MT_DOWNLOAD,            /* Download a component */
+       MT_SPEW_SECTION         /* Download a component in a single operation */
 };
 
 /*
index 0586e0bd2a08a3fbf72fb031a12c5b0fa0bb0573..8bba36148ad6ede539a837a43538f1c9e26ef47b 100644 (file)
@@ -1950,6 +1950,14 @@ appropriate ERROR code will be returned; otherwise, if the open is successful,
 this command will succeed returning the same information as an OPEN command.
 
 
+ DLAT   (DownLoad ATtachment)
+
+ Similar to OPNA, and with the same calling syntax.  The difference is that
+instead of opening a download file for block transfer, this command outputs the
+entire decoded MIME section at once, using a BINARY_FOLLOWS response.  This is
+useful for outputting small objects such as calendar items.
  GEXP   (Get instant messages)
 
  This is a more sophisticated way of retrieving instant messages than the old