Added the OPNA command for downloading attachments
authorArt Cancro <ajc@citadel.org>
Mon, 1 Feb 1999 02:22:41 +0000 (02:22 +0000)
committerArt Cancro <ajc@citadel.org>
Mon, 1 Feb 1999 02:22:41 +0000 (02:22 +0000)
citadel/ChangeLog
citadel/citserver.c
citadel/file_ops.c
citadel/file_ops.h
citadel/msgbase.c
citadel/msgbase.h
citadel/server.h
citadel/techdoc/session.txt

index 1a50c2fd437fc206fd002b1de1eb1965a0c73981..dfb75e731c3f98333eb108bc806c4c13e9f8c430 100644 (file)
@@ -2,6 +2,7 @@ Sun Jan 31 18:29:18 EST 1999 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
        * Added qpdecode.c to the distribution (decodes quoted-printable)
        * Finished the MIME parser
        * Gave MSG0 a reasonable behaviour for MIME messages
+       * Added the OPNA command for downloading attachments
 
 Sat Jan 30 18:39:53 EST 1999 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
        * Look for citadel.rc in current directory if not found elsewhere
index 95a3214118ca1ff3c6246cae42cbc2b11ad6bc88..70fa577fd06eca78357d95369ca57d9b491e77b9 100644 (file)
@@ -838,6 +838,10 @@ void *context_loop(struct CitContext *con)
                        cmd_msg4(&cmdbuf[5]);
                        }
 
+               else if (!strncasecmp(cmdbuf,"OPNA",4)) {
+                       cmd_opna(&cmdbuf[5]);
+                       }
+
                else if (!strncasecmp(cmdbuf,"INFO",4)) {
                        cmd_info();
                        }
index 40d8289e33d2c79d04a13e8ff4dbe63795bb9d3d..e808766696e6f1eca7bcb63a37854b72cffd60e9 100644 (file)
@@ -229,11 +229,12 @@ void cmd_netf(char *cmdbuf)
  * It examines the file and displays the OK result code and some information
  * about the file.  NOTE: this stuff is Unix dependent.
  */
-void OpenCmdResult(void) {
+void OpenCmdResult(char *filename, char *mime_type) {
        struct stat statbuf;
 
        fstat(fileno(CC->download_fp), &statbuf);
-       cprintf("%d %ld|%ld\n", OK, statbuf.st_size, statbuf.st_mtime);
+       cprintf("%d %ld|%ld|%s|%s\n", OK, statbuf.st_size, statbuf.st_mtime,
+                                       filename, mime_type);
        }
 
 
@@ -282,7 +283,7 @@ void cmd_open(char *cmdbuf)
                return;
                }
 
-       OpenCmdResult();
+       OpenCmdResult(filename, "application/octet-stream");
        }
 
 /*
@@ -342,7 +343,7 @@ void cmd_oimg(char *cmdbuf)
                return;
                }
        
-       OpenCmdResult();
+       OpenCmdResult(pathname, "image/gif");
        }
 
 /*
index 54f25d2dc7daa054dd05d0fd6c02f19ca5ca66aa..014ae556b393b3b4b16263051dee6dc2258fe477 100644 (file)
@@ -2,7 +2,7 @@
 void cmd_delf (char *filename);
 void cmd_movf (char *cmdbuf);
 void cmd_netf (char *cmdbuf);
-void OpenCmdResult (void);
+void OpenCmdResult (char *, char *);
 void cmd_open (char *cmdbuf);
 void cmd_oimg (char *cmdbuf);
 void cmd_uopn (char *cmdbuf);
index 5fb3c4b6c6229eab92d54ddf388560332778d1a2..9a037ea3cacfd75195ee42d366c5af94caea38d9 100644 (file)
@@ -18,6 +18,7 @@
 #include "sysdep_decls.h"
 #include "room_ops.h"
 #include "user_ops.h"
+#include "file_ops.h"
 #include "control.h"
 #include "dynloader.h"
 #include "tools.h"
@@ -362,6 +363,41 @@ void fixed_output(char *name, char *filename, char *partnum, char *disp,
        }
 
 
+/*
+ * Callback function for mime parser that opens a section for downloading
+ */
+void mime_download(char *name, char *filename, char *partnum, char *disp,
+                        void *content, char *cbtype, size_t length) {
+
+       char tmpname[PATH_MAX];
+       static int seq = 0;
+
+       /* Silently go away if there's already a download open... */
+       if (CC->download_fp != NULL) return;
+
+       /* ...or if this is not the desired section */
+       if (strcasecmp(CC->desired_section, partnum)) return;
+
+       snprintf(tmpname, sizeof tmpname,
+               "/tmp/CitServer.download.%4x.%4x", getpid(), ++seq);
+
+       CC->download_fp = fopen(tmpname, "wb+");
+       if (CC->download_fp == NULL) return;
+
+       /* Unlink the file while it's open, to guarantee that the
+        * temp file will always be deleted.
+        */
+       unlink(tmpname);
+
+       fwrite(content, length, 1, CC->download_fp);
+       fflush(CC->download_fp);
+       rewind(CC->download_fp);
+
+       OpenCmdResult(filename, cbtype);
+       }
+
+
+
 /*
  * Get a message off disk.  (return value is the message's timestamp)
  * 
@@ -450,6 +486,41 @@ time_t output_message(char *msgid, int mode, int headers_only) {
        anon_flag = *mptr++;
        format_type = *mptr++;
 
+       /* Are we downloading a MIME component? */
+       if (mode == MT_DOWNLOAD) {
+               if (format_type != 4) {
+                       cprintf("%d This is not a MIME message.\n",
+                               ERROR);
+                       }
+               else if (CC->download_fp != NULL) {
+                       cprintf("%d You already have a download open.\n",
+                               ERROR);
+                       }
+               else {
+                       /* Skip to the message body */
+                       while(ch = *mptr++, (ch!='M' && ch!=0)) {
+                               buf[0] = 0;
+                               do {
+                                       buf[strlen(buf)+1] = 0;
+                                       rch = *mptr++;
+                                       buf[strlen(buf)] = rch;
+                                       } while (rch > 0);
+                               }
+                       /* Now parse it */
+                       mime_parser(mptr, NULL, *mime_download);
+                       /* If there's no file open by this time, the requested
+                        * section wasn't found, so print an error
+                        */
+                       if (CC->download_fp == NULL) {
+                               cprintf("%d Section %s not found.\n",
+                                       ERROR+FILE_NOT_FOUND,
+                                       CC->desired_section);
+                               }
+                       }
+               cdb_free(dmsgtext);
+               return(xtime);
+               }
+
        /* Are we just looking for the message date? */
        if (mode == MT_DATE) while(ch = *mptr++, (ch!='M' && ch!=0)) {
                buf[0] = 0;
@@ -697,6 +768,21 @@ void cmd_msg4(char *cmdbuf)
 
 
 
+/*
+ * Open a component of a MIME message as a download file 
+ */
+void cmd_opna(char *cmdbuf)
+{
+       char msgid[256];
+
+       extract(msgid, cmdbuf, 0);
+       extract(CC->desired_section, cmdbuf, 1);
+
+       output_message(msgid, MT_DOWNLOAD, 0);
+       }
+
+
+
 /*
  * Message base operation to send a message to the master file
  * (returns new message number)
index aa969dba24ab58154e00c1e21386f5e47d249912..4331d598b099bca73e48534bd18dfb5120449ba4 100644 (file)
@@ -6,11 +6,12 @@ void help_subst (char *strbuf, char *source, char *dest);
 void do_help_subst (char *buffer);
 void memfmout (int width, char *mptr, char subst);
 void output_mime_parts(char *);
-time_t output_message (char *msgid, int mode, int headers_only);
+time_t output_message (char *, int, int);
 void cmd_msg0 (char *cmdbuf);
 void cmd_msg2 (char *cmdbuf);
 void cmd_msg3 (char *cmdbuf);
 void cmd_msg4 (char *cmdbuf);
+void cmd_opna (char *cmdbuf);
 long int send_message (char *message_in_memory, size_t message_length,
                       int generate_id);
 void loadtroom (void);
index 4f5a87fc0566fea0f9d81873c0f3a72c704461ed..a7a93c1b2979e1d0a239bfd508efc585be469cc6 100644 (file)
@@ -36,7 +36,7 @@ struct CitContext {
        int client_socket;
        char *ExpressMessages;
        int cs_pid;                     /* session ID */
-       char cs_room[20];               /* current room */
+       char cs_room[ROOMNAMELEN];      /* current room */
        time_t cs_lastupdt;             /* time of last update */
        time_t lastcmd;                 /* time of last command executed */
        time_t lastidle;                /* For computing idle time */
@@ -67,6 +67,7 @@ struct CitContext {
        char last_pager[32];            /* The username of the last pager    */
 
        int FloorBeingSearched;         /* This is used by cmd_lrms() etc.   */
+       char desired_section[64];       /* This is used for MIME downloads   */
        };
 
 typedef struct CitContext t_context;
@@ -124,6 +125,7 @@ struct ChatLine {
 #define MT_RFC822      2               /* RFC822 */
 #define MT_RAW         3               /* IGnet raw format */
 #define MT_MIME                4               /* MIME-formatted message */
+#define MT_DOWNLOAD    5               /* Download a component */
 
 
 /*
index a857929b83f7457ba2eb611c4a725493732cf004..f535a74c81ae3240f1f2459cb3945e7eece5c004 100644 (file)
@@ -1001,8 +1001,8 @@ file resides.  Possible return codes are:
  OK                            (file is open)
  
  If the file is successfully opened, OK will be returned, along with the
-size (in bytes) of the file, and (in version 5.00 and above) the time of last
-modification.
+size (in bytes) of the file, the time of last modification (if applicable),
+the filename (if known), and the MIME type of the file (if known).
  
  
  CLOS   (CLOSe the download file)
@@ -1635,3 +1635,19 @@ succeeds; otherwise it returns an ERROR code.
  
  This command is probably temporary, until we can work some sort of scheduler
 into the system.  It is implemented in the serv_expire module.
+  
+ MSG4   (read MeSsaGe, mode 4 -- enumerate MIME parts)
+     FIX ... do the writeup for this once it's done.
+
+  
+ OPNA   (OPeN Attachment)
+ Opens, as a download file, a component of a MIME-encoded message.  The two
+parameters which must be passed to this command are the message number and the
+name of the desired section.  If the message or section does not exist, an
+appropriate ERROR code will be returned; otherwise, if the open is successful,
+this command will succeed returning the same information as an OPEN command.