]> code.citadel.org Git - citadel.git/commitdiff
* File and attachment downloads now use the new IPC code.
authorMichael Hampton <io_error@uncensored.citadel.org>
Sun, 29 Sep 2002 04:55:13 +0000 (04:55 +0000)
committerMichael Hampton <io_error@uncensored.citadel.org>
Sun, 29 Sep 2002 04:55:13 +0000 (04:55 +0000)
* Implemented high-speed pipelined file download in IPC code.

citadel/ChangeLog
citadel/citadel_ipc.c
citadel/citadel_ipc.h
citadel/ipc.h
citadel/ipc_c_tcp.c
citadel/messages.c
citadel/rooms.c
citadel/rooms.h
citadel/routines.c

index 34a94238c315f59a2ca75c629a90eef93562a7c3..80c2a2337649e808b7b9ec26bbd14e0b3a6a81ed 100644 (file)
@@ -1,4 +1,8 @@
  $Log$
+ Revision 601.11  2002/09/29 04:55:13  error
+ * File and attachment downloads now use the new IPC code.
+ * Implemented high-speed pipelined file download in IPC code.
+
  Revision 601.10  2002/09/29 04:41:43  error
  * file_ops.c: cmd_read() now returns a short read at end-of-file instead of
    4096, this prevents trailing garbage on the downloaded file; also it now
@@ -4022,3 +4026,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import
+
index 7c7193a96387ec3b13a84523cb17286cd8789a2b..07f13ac9f77933f3634bd0a6993f8c5cefa4fb67 100644 (file)
@@ -31,10 +31,6 @@ pthread_mutex_t rwlock;
 #endif
 char express_msgs = 0;
 
-static volatile int download_in_progress = 0;  /* download file open */
-static volatile int upload_in_progress = 0;    /* upload file open */
-/* static volatile int serv_sock; */   /* Socket on which we talk to server */
-
 
 /*
  * Does nothing.  The server should always return 200.
@@ -1049,7 +1045,8 @@ int CtdlIPCOnlineUsers(CtdlIPC *ipc, char **listing, time_t *stamp, char *cret)
 
 
 /* OPEN */
-int CtdlIPCFileDownload(CtdlIPC *ipc, const char *filename, void **buf, char *cret)
+int CtdlIPCFileDownload(CtdlIPC *ipc, const char *filename, void **buf,
+               void (*progress_gauge_callback)(long, long), char *cret)
 {
        register int ret;
        size_t bytes;
@@ -1061,7 +1058,7 @@ int CtdlIPCFileDownload(CtdlIPC *ipc, const char *filename, void **buf, char *cr
        if (!filename) return -2;
        if (!buf) return -2;
        if (*buf) return -2;
-       if (download_in_progress) return -2;
+       if (ipc->downloading) return -2;
 
        aaa = (char *)malloc(strlen(filename) + 6);
        if (!aaa) return -1;
@@ -1069,13 +1066,13 @@ int CtdlIPCFileDownload(CtdlIPC *ipc, const char *filename, void **buf, char *cr
        sprintf(aaa, "OPEN %s", filename);
        ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
        free(aaa);
-       /* FIXME: Possible race condition */
        if (ret / 100 == 2) {
-               download_in_progress = 1;
+               ipc->downloading = 1;
                bytes = extract_long(cret, 0);
                last_mod = extract_int(cret, 1);
                extract(mimetype, cret, 2);
-               ret = CtdlIPCReadDownload(ipc, buf, bytes, cret);
+               ret = CtdlIPCReadDownload(ipc, buf, bytes, progress_gauge_callback, cret);
+/*             ret = CtdlIPCHighSpeedReadDownload(ipc, buf, bytes, progress_gauge_callback, cret); */
                ret = CtdlIPCEndDownload(ipc, cret);
                if (ret / 100 == 2)
                        sprintf(cret, "%d|%ld|%s|%s", bytes, last_mod,
@@ -1087,7 +1084,7 @@ int CtdlIPCFileDownload(CtdlIPC *ipc, const char *filename, void **buf, char *cr
 
 /* OPNA */
 int CtdlIPCAttachmentDownload(CtdlIPC *ipc, long msgnum, const char *part, void **buf,
-               char *cret)
+               void (*progress_gauge_callback)(long, long), char *cret)
 {
        register int ret;
        size_t bytes;
@@ -1101,7 +1098,7 @@ int CtdlIPCAttachmentDownload(CtdlIPC *ipc, long msgnum, const char *part, void
        if (*buf) return -2;
        if (!part) return -2;
        if (!msgnum) return -2;
-       if (download_in_progress) return -2;
+       if (ipc->downloading) return -2;
 
        aaa = (char *)malloc(strlen(part) + 17);
        if (!aaa) return -1;
@@ -1109,13 +1106,12 @@ int CtdlIPCAttachmentDownload(CtdlIPC *ipc, long msgnum, const char *part, void
        sprintf(aaa, "OPNA %ld|%s", msgnum, part);
        ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
        free(aaa);
-       /* FIXME: Possible race condition */
        if (ret / 100 == 2) {
-               download_in_progress = 1;
+               ipc->downloading = 1;
                bytes = extract_long(cret, 0);
                last_mod = extract_int(cret, 1);
                extract(mimetype, cret, 2);
-               ret = CtdlIPCReadDownload(ipc, buf, bytes, cret);
+               ret = CtdlIPCHighSpeedReadDownload(ipc, buf, bytes, progress_gauge_callback, cret);
                ret = CtdlIPCEndDownload(ipc, cret);
                if (ret / 100 == 2)
                        sprintf(cret, "%d|%ld|%s|%s", bytes, last_mod,
@@ -1126,7 +1122,8 @@ int CtdlIPCAttachmentDownload(CtdlIPC *ipc, long msgnum, const char *part, void
 
 
 /* OIMG */
-int CtdlIPCImageDownload(CtdlIPC *ipc, const char *filename, void **buf, char *cret)
+int CtdlIPCImageDownload(CtdlIPC *ipc, const char *filename, void **buf,
+               void (*progress_gauge_callback)(long, long), char *cret)
 {
        register int ret;
        size_t bytes;
@@ -1138,7 +1135,7 @@ int CtdlIPCImageDownload(CtdlIPC *ipc, const char *filename, void **buf, char *c
        if (!buf) return -1;
        if (*buf) return -1;
        if (!filename) return -1;
-       if (download_in_progress) return -1;
+       if (ipc->downloading) return -1;
 
        aaa = (char *)malloc(strlen(filename) + 6);
        if (!aaa) return -1;
@@ -1146,13 +1143,12 @@ int CtdlIPCImageDownload(CtdlIPC *ipc, const char *filename, void **buf, char *c
        sprintf(aaa, "OIMG %s", filename);
        ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
        free(aaa);
-       /* FIXME: Possible race condition */
        if (ret / 100 == 2) {
-               download_in_progress = 1;
+               ipc->downloading = 1;
                bytes = extract_long(cret, 0);
                last_mod = extract_int(cret, 1);
                extract(mimetype, cret, 2);
-               ret = CtdlIPCReadDownload(ipc, buf, bytes, cret);
+               ret = CtdlIPCReadDownload(ipc, buf, bytes, progress_gauge_callback, cret);
                ret = CtdlIPCEndDownload(ipc, cret);
                if (ret / 100 == 2)
                        sprintf(cret, "%d|%ld|%s|%s", bytes, last_mod,
@@ -1172,7 +1168,7 @@ int CtdlIPCFileUpload(CtdlIPC *ipc, const char *filename, const char *comment, v
        if (!cret) return -1;
        if (!filename) return -1;
        if (!comment) return -1;
-       if (upload_in_progress) return -1;
+       if (ipc->uploading) return -1;
 
        aaa = (char *)malloc(strlen(filename) + strlen(comment) + 7);
        if (!aaa) return -1;
@@ -1180,9 +1176,8 @@ int CtdlIPCFileUpload(CtdlIPC *ipc, const char *filename, const char *comment, v
        sprintf(aaa, "UOPN %s|%s", filename, comment);
        ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
        free(aaa);
-       /* FIXME: Possible race condition */
        if (ret / 100 == 2)
-               upload_in_progress = 1;
+               ipc->uploading = 1;
        ret = CtdlIPCWriteUpload(ipc, buf, bytes, cret);
        ret = CtdlIPCEndUpload(ipc, cret);
        return ret;
@@ -1198,7 +1193,7 @@ int CtdlIPCImageUpload(CtdlIPC *ipc, int for_real, const char *filename, size_t
 
        if (!cret) return -1;
        if (!filename) return -1;
-       if (upload_in_progress) return -1;
+       if (ipc->uploading) return -1;
 
        aaa = (char *)malloc(strlen(filename) + 17);
        if (!aaa) return -1;
@@ -1206,9 +1201,8 @@ int CtdlIPCImageUpload(CtdlIPC *ipc, int for_real, const char *filename, size_t
        sprintf(aaa, "UIMG %d|%s", for_real, filename);
        ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
        free(aaa);
-       /* FIXME: Possible race condition */
        if (ret / 100 == 2)
-               upload_in_progress = 1;
+               ipc->uploading = 1;
        return ret;
 }
 
@@ -1894,7 +1888,7 @@ size_t CtdlIPCPartialRead(CtdlIPC *ipc, void **buf, size_t offset, size_t bytes,
                *buf = (void *)realloc(*buf, (size_t)(offset + len));
                if (*buf) {
                        /* I know what I'm doing */
-                       serv_read(ipc, (char *)&buf[offset], len);
+                       serv_read(ipc, (*buf + offset), len);
                } else {
                        /* We have to read regardless */
                        serv_read(ipc, aaa, len);
@@ -1912,11 +1906,11 @@ int CtdlIPCEndDownload(CtdlIPC *ipc, char *cret)
        register int ret;
 
        if (!cret) return -2;
-       if (!download_in_progress) return -2;
+       if (!ipc->downloading) return -2;
 
        ret = CtdlIPCGenericCommand(ipc, "CLOS", NULL, 0, NULL, NULL, cret);
        if (ret / 100 == 2)
-               download_in_progress = 0;
+               ipc->downloading = 0;
        return ret;
 }
 
@@ -1934,38 +1928,96 @@ int CtdlIPCSpecifyPreferredFormats(CtdlIPC *ipc, char *cret, char *formats) {
 
 
 /* READ */
-int CtdlIPCReadDownload(CtdlIPC *ipc, void **buf, size_t bytes, char *cret)
+int CtdlIPCReadDownload(CtdlIPC *ipc, void **buf, size_t bytes,
+              void (*progress_gauge_callback)(long, long), char *cret)
 {
        register size_t len;
 
        if (!cret) return -1;
        if (!buf) return -1;
        if (*buf) return -1;
-       if (!download_in_progress) return -1;
+       if (!ipc->downloading) return -1;
 
        len = 0;
+       if (progress_gauge_callback)
+               progress_gauge_callback(len, bytes);
        while (len < bytes) {
-               len = CtdlIPCPartialRead(ipc, buf, len, 4096, cret);
-               if (len == -1) {
+               register size_t block;
+
+               block = CtdlIPCPartialRead(ipc, buf, len, 4096, cret);
+               if (block == -1) {
                        free(*buf);
                        return 0;
                }
+               len += block;
+               if (progress_gauge_callback)
+                       progress_gauge_callback(len, bytes);
        }
        return len;
 }
 
 
+/* READ - pipelined */
+int CtdlIPCHighSpeedReadDownload(CtdlIPC *ipc, void **buf, size_t bytes,
+              void (*progress_gauge_callback)(long, long), char *cret)
+{
+       register size_t len;
+       register int calls;     /* How many calls in the pipeline */
+       register int i;         /* iterator */
+       char aaa[4096];
+
+       if (!cret) return -1;
+       if (!buf) return -1;
+       if (*buf) return -1;
+       if (!ipc->downloading) return -1;
+
+       *buf = (void *)realloc(*buf, bytes);
+       if (!*buf) return -1;
+
+       len = 0;
+       CtdlIPC_lock(ipc);
+       if (progress_gauge_callback)
+               progress_gauge_callback(len, bytes);
+
+       /* How many calls will be in the pipeline? */
+       calls = bytes / 4096;
+       if (bytes % 4096) calls++;
+
+       /* Send all requests at once */
+       for (i = 0; i < calls; i++) {
+               sprintf(aaa, "READ %d|4096", i * 4096);
+               CtdlIPC_putline(ipc, aaa);
+       }
+
+       /* Receive all responses at once */
+       for (i = 0; i < calls; i++) {
+               CtdlIPC_getline(ipc, aaa);
+               if (aaa[0] != '6')
+                       strcpy(cret, &aaa[4]);
+               else {
+                       len = extract_long(&aaa[4], 0);
+                       /* I know what I'm doing */
+                       serv_read(ipc, ((*buf) + (i * 4096)), len);
+               }
+               if (progress_gauge_callback)
+                       progress_gauge_callback(i * 4096 + len, bytes);
+       }
+       CtdlIPC_unlock(ipc);
+       return len;
+}
+
+
 /* UCLS */
 int CtdlIPCEndUpload(CtdlIPC *ipc, char *cret)
 {
        register int ret;
 
        if (!cret) return -1;
-       if (!upload_in_progress) return -1;
+       if (!ipc->uploading) return -1;
 
        ret = CtdlIPCGenericCommand(ipc, "UCLS", NULL, 0, NULL, NULL, cret);
        if (ret / 100 == 2)
-               upload_in_progress = 0;
+               ipc->uploading = 0;
        return ret;
 }
 
index 824befc61fd20810d8f5c3ba87f25421d40db013..3b45e9ee55b6ab5983918556eb086e00738b95b8 100644 (file)
@@ -107,10 +107,12 @@ int CtdlIPCDeleteFile(CtdlIPC *ipc, const char *filename, char *cret);
 int CtdlIPCMoveFile(CtdlIPC *ipc, const char *filename, const char *destroom, char *cret);
 int CtdlIPCNetSendFile(CtdlIPC *ipc, const char *filename, const char *destnode, char *cret);
 int CtdlIPCOnlineUsers(CtdlIPC *ipc, char **listing, time_t *stamp, char *cret);
-int CtdlIPCFileDownload(CtdlIPC *ipc, const char *filename, void **buf, char *cret);
+int CtdlIPCFileDownload(CtdlIPC *ipc, const char *filename, void **buf,
+               void (*progress_gauge_callback)(long, long), char *cret);
 int CtdlIPCAttachmentDownload(CtdlIPC *ipc, long msgnum, const char *part, void **buf,
-               char *cret);
-int CtdlIPCImageDownload(CtdlIPC *ipc, const char *filename, void **buf, char *cret);
+               void (*progress_gauge_callback)(long, long), char *cret);
+int CtdlIPCImageDownload(CtdlIPC *ipc, const char *filename, void **buf,
+               void (*progress_gauge_callback)(long, long), char *cret);
 int CtdlIPCFileUpload(CtdlIPC *ipc, const char *filename, const char *comment, void *buf,
                size_t bytes, char *cret);
 int CtdlIPCImageUpload(CtdlIPC *ipc, int for_real, const char *filename, size_t bytes,
@@ -171,7 +173,10 @@ size_t CtdlIPCPartialRead(CtdlIPC *ipc, void **buf, size_t offset, size_t bytes,
 int CtdlIPCEndUpload(CtdlIPC *ipc, char *cret);
 int CtdlIPCWriteUpload(CtdlIPC *ipc, void *buf, size_t bytes, char *cret);
 int CtdlIPCEndDownload(CtdlIPC *ipc, char *cret);
-int CtdlIPCReadDownload(CtdlIPC *ipc, void **buf, size_t bytes, char *cret);
+int CtdlIPCReadDownload(CtdlIPC *ipc, void **buf, size_t bytes,
+              void (*progress_gauge_callback)(long, long), char *cret);
+int CtdlIPCHighSpeedReadDownload(CtdlIPC *ipc, void **buf, size_t bytes,
+              void (*progress_gauge_callback)(long, long), char *cret);
 int CtdlIPCGenericCommand(CtdlIPC *ipc, const char *command, const char *to_send,
                size_t bytes_to_send, char **to_receive,
                size_t *bytes_to_receive, char *proto_response);
index 2181bf7225c3d94c182f4dfb890d7473ddbb2ebe..41c8856791809cacb6d60470eeb6e91498c9fb17 100644 (file)
@@ -34,6 +34,10 @@ typedef struct _CtdlIPC {
        int sock;
        /* 1 if server is local, 0 otherwise or if not connected */
        int isLocal;
+       /* 1 if a download is open on the server, 0 otherwise */
+       int downloading;
+       /* 1 if an upload is open on the server, 0 otherwise */
+       int uploading;
 } CtdlIPC;
 
 /* C constructor */
index dd0994e4ce3d5bd2cf56bead806f5aa991b9263b..b051f6876cff822a347c6c167c4e17b0bec8cc79 100644 (file)
@@ -302,6 +302,8 @@ CtdlIPC* CtdlIPC_new(int argc, char **argv, char *hostbuf, char *portbuf)
 #endif
        ipc->sock = -1;                 /* Not connected */
        ipc->isLocal = 0;               /* Not local, of course! */
+       ipc->downloading = 0;
+       ipc->uploading = 0;
 
        strcpy(cithost, DEFAULT_HOST);  /* default host */
        strcpy(citport, DEFAULT_PORT);  /* default port */
index e2fd7e761045919ff52a04696580681c33b6dd02..1f796d8a19ff1ed99e376f366abc909cef4ac3e3 100644 (file)
@@ -60,6 +60,7 @@ int haschar(const char *st, int ch);
 void getline(char *string, int lim);
 int file_checksum(char *filename);
 void do_edit(char *desc, char *read_cmd, char *check_cmd, char *write_cmd);
+void progress(long int curr, long int cmax);
 
 long *msg_arr = NULL;
 int msg_arr_size = 0;
@@ -1244,7 +1245,9 @@ void readmsgs(CtdlIPC *ipc,
        char pagin;
        char cmd[SIZ];
        char targ[ROOMNAMELEN];
-       char filename[SIZ];
+       char filename[PATH_MAX];
+       char save_to[PATH_MAX];
+       void *attachment = NULL;        /* Downloaded attachment */
        FILE *dest = NULL;      /* Alternate destination other than screen */
        int r;                          /* IPC response code */
 
@@ -1533,18 +1536,20 @@ RMSGREAD:       scr_flush();
                case 'f':
                        newprompt("Which section? ", filename,
                                  ((sizeof filename) - 1));
-                       snprintf(cmd, sizeof cmd,
-                                "OPNA %ld|%s", msg_arr[a], filename);
-                       CtdlIPC_putline(ipc, cmd);
-                       CtdlIPC_getline(ipc, cmd);
-                       if (cmd[0] == '2') {
-                               extract(filename, &cmd[4], 2);
-                               download_to_local_disk(ipc, filename,
-                                                      extract_int(&cmd[4],
-                                                                  0));
+                       r = CtdlIPCAttachmentDownload(ipc, msg_arr[a],
+                                       filename, &attachment, progress, cmd);
+                       extract(filename, cmd, 2);
+                       destination_directory(save_to, filename);
+                       r = CtdlIPCAttachmentDownload(ipc, msg_arr[a],
+                               filename, &attachment, progress, cmd);
+                       if (r / 100 != 2) {
+                               scr_printf("%s\n", cmd);
                        } else {
-                               scr_printf("%s\n", &cmd[4]);
+                               save_buffer(attachment,
+                                               extract_long(cmd, 0),
+                                               save_to);
                        }
+                       if (attachment) free(attachment);
                        goto RMSGREAD;
                case 'd':
                        scr_printf("*** Delete this message? ");
index 62ec79e00bfb0f31bc21effb9ad1731d6f07654f..c97533a840a80ad65ef9c47ed19ec9c55f9b2e03 100644 (file)
@@ -598,73 +598,51 @@ void ungoto(CtdlIPC *ipc)
 }
 
 
-/* Here's the code for simply transferring the file to the client,
- * for folks who have their own clientware.  It's a lot simpler than
- * the [XYZ]modem code below...
- * (This function assumes that a download file is already open on the server)
+/*
+ * saves filelen bytes from file at pathname
  */
-void download_to_local_disk(CtdlIPC *ipc,
-               char *supplied_filename, long total_bytes)
+int save_buffer(void *file, size_t filelen, const char *pathname)
 {
-       char buf[SIZ];
-       char dbuf[4096];
-       long transmitted_bytes = 0L;
-       long aa, bb;
-       FILE *savefp;
-       int broken = 0;
-       int packet;
-       char filename[SIZ];
+       size_t block = 0;
+       size_t bytes_written = 0;
+       FILE *fp;
 
-       strcpy(filename, supplied_filename);
-       if (strlen(filename) == 0) {
-               newprompt("Filename: ", filename, 250);
+       fp = fopen(pathname, "w");
+       if (!fp) {
+               err_printf("Cannot open '%s': %s\n", pathname, strerror(errno));
+               return 0;
        }
+       do {
+               block = fwrite(file + bytes_written, 1,
+                               filelen - bytes_written, fp);
+               bytes_written += block;
+       } while (errno == EINTR && bytes_written < filelen);
+       fclose(fp);
 
-       scr_printf("Enter the name of the directory to save '%s'\n"
-               "to, or press return for the current directory.\n", filename);
-       newprompt("Directory: ", dbuf, sizeof dbuf);
-       if (strlen(dbuf) == 0)
-               strcpy(dbuf, ".");
-       strcat(dbuf, "/");
-       strcat(dbuf, filename);
-
-       savefp = fopen(dbuf, "w");
-       if (savefp == NULL) {
-               scr_printf("Cannot open '%s': %s\n", dbuf, strerror(errno));
-               /* close the download file at the server */
-               CtdlIPC_putline(ipc, "CLOS");
-               CtdlIPC_getline(ipc, buf);
-               if (buf[0] != '2') {
-                       scr_printf("%s\n", &buf[4]);
-               }
-               return;
-       }
-       progress(0, total_bytes);
-       while ((transmitted_bytes < total_bytes) && (broken == 0)) {
-               bb = total_bytes - transmitted_bytes;
-               aa = ((bb < 4096) ? bb : 4096);
-               snprintf(buf, sizeof buf, "READ %ld|%ld", transmitted_bytes, aa);
-               CtdlIPC_putline(ipc, buf);
-               CtdlIPC_getline(ipc, buf);
-               if (buf[0] != '6') {
-                       scr_printf("%s\n", &buf[4]);
-                       return;
-               }
-               packet = extract_int(&buf[4], 0);
-               serv_read(ipc, dbuf, packet);
-               if (fwrite(dbuf, packet, 1, savefp) < 1)
-                       broken = 1;
-               transmitted_bytes = transmitted_bytes + (long) packet;
-               progress(transmitted_bytes, total_bytes);
-       }
-       fclose(savefp);
-       /* close the download file at the server */
-       CtdlIPC_putline(ipc, "CLOS");
-       CtdlIPC_getline(ipc, buf);
-       if (buf[0] != '2') {
-               scr_printf("%s\n", &buf[4]);
+       if (bytes_written < filelen) {
+               err_printf("Trouble saving '%s': %s\n", pathname,
+                               strerror(errno));
+               return 0;
        }
-       return;
+       return 1;
+}
+
+
+/*
+ * Save supplied_filename in dest directory; gets the name only
+ */
+void destination_directory(char *dest, const char *supplied_filename)
+{
+       scr_printf("Enter the name of the directory to save '%s'\n"
+               "to, or press return for the current directory.\n",
+               supplied_filename);
+       newprompt("Directory: ", dest, PATH_MAX);
+       if (strlen(dest) == 0) {
+               dest[0] = '.';
+               dest[1] = 0;
+       }
+       strcat(dest, "/");
+       strcat(dest, supplied_filename);
 }
 
 
@@ -676,72 +654,55 @@ void download_to_local_disk(CtdlIPC *ipc,
 void download(CtdlIPC *ipc, int proto)
 {
        char buf[SIZ];
-       char filename[SIZ];
-       char tempname[SIZ];
+       char filename[PATH_MAX];
+       char tempname[PATH_MAX];
        char transmit_cmd[SIZ];
-       long total_bytes = 0L;
-       char dbuf[4096];
-       long transmitted_bytes = 0L;
-       long aa, bb;
-       int packet;
        FILE *tpipe = NULL;
        int broken = 0;
+       int r;
+       void *file = NULL;      /* The downloaded file */
+       long filelen = 0L;      /* The downloaded file length */
 
        if ((room_flags & QR_DOWNLOAD) == 0) {
                scr_printf("*** You cannot download from this room.\n");
                return;
        }
 
-       newprompt("Enter filename: ", filename, 255);
+       newprompt("Enter filename: ", filename, PATH_MAX);
 
-       snprintf(buf, sizeof buf, "OPEN %s", filename);
-       CtdlIPC_putline(ipc, buf);
-       CtdlIPC_getline(ipc, buf);
-       if (buf[0] != '2') {
-               scr_printf("%s\n", &buf[4]);
+       /* Save to local disk, for folks with their own copy of the client */
+       if (proto == 5) {
+               destination_directory(tempname, filename);
+               r = CtdlIPCFileDownload(ipc, filename, &file, progress, buf);
+               if (r / 100 != 2) {
+                       scr_printf("%s\n", buf);
+                       return;
+               }
+               save_buffer(file, extract_long(buf, 0), tempname);
+               free(file);
                return;
        }
-       total_bytes = extract_long(&buf[4], 0);
 
-       /* Save to local disk, for folks with their own copy of the client */
-       if (proto == 5) {
-               download_to_local_disk(ipc, filename, total_bytes);
+       r = CtdlIPCFileDownload(ipc, filename, &file, progress, buf);
+       if (r / 100 != 2) {
+               scr_printf("%s\n", buf);
                return;
        }
+       filelen = extract_long(buf, 0);
 
        /* Meta-download for public clients */
-       scr_printf("Fetching file from Citadel server...\n");
+       /* scr_printf("Fetching file from Citadel server...\n"); */
        mkdir(tempdir, 0700);
        snprintf(tempname, sizeof tempname, "%s/%s", tempdir, filename);
        tpipe = fopen(tempname, "wb");
-       while ((transmitted_bytes < total_bytes) && (broken == 0)) {
-               progress(transmitted_bytes, total_bytes);
-               bb = total_bytes - transmitted_bytes;
-               aa = ((bb < 4096) ? bb : 4096);
-               snprintf(buf, sizeof buf, "READ %ld|%ld", transmitted_bytes, aa);
-               CtdlIPC_putline(ipc, buf);
-               CtdlIPC_getline(ipc, buf);
-               if (buf[0] != '6') {
-                       scr_printf("%s\n", &buf[4]);
-               }
-               packet = extract_int(&buf[4], 0);
-               serv_read(ipc, dbuf, packet);
-               if (fwrite(dbuf, packet, 1, tpipe) < 1) {
-                       broken = 1;
-               }
-               transmitted_bytes = transmitted_bytes + (long) packet;
+       if (fwrite(file, filelen, 1, tpipe) < filelen) {
+               broken = 1;
        }
        fclose(tpipe);
-       progress(transmitted_bytes, total_bytes);
-
-       /* close the download file at the server */
-       CtdlIPC_putline(ipc, "CLOS");
-       CtdlIPC_getline(ipc, buf);
-       if (buf[0] != '2') {
-               scr_printf("%s\n", &buf[4]);
-       }
+       if (file) free(file);
 
        if (proto == 0) {
+               /* FIXME: display internally instead */
                snprintf(transmit_cmd, sizeof transmit_cmd,
                        "SHELL=/dev/null; export SHELL; TERM=dumb; export TERM; exec more -d <%s",
                        tempname);
@@ -753,6 +714,7 @@ void download(CtdlIPC *ipc, int proto)
        else if (proto == 4)
                snprintf(transmit_cmd, sizeof transmit_cmd, "exec sz %s", tempname);
        else
+               /* FIXME: display internally instead */
                snprintf(transmit_cmd, sizeof transmit_cmd, "exec cat %s", tempname);
 
        screen_reset();
@@ -763,7 +725,7 @@ void download(CtdlIPC *ipc, int proto)
 
        /* clean up the temporary directory */
        nukedir(tempdir);
-       scr_putc(7);
+       scr_putc(7);    /* Beep beep! */
 }
 
 
index 1b54cdd41f42b50bc1a71d45c46bd2a775b1410f..7e53bb20d4dee52a4eb6ca05c7f5d32456192eca 100644 (file)
@@ -18,8 +18,9 @@ void create_floor(CtdlIPC *ipc);
 void edit_floor(CtdlIPC *ipc);
 void kill_floor(CtdlIPC *ipc);
 void enter_bio(CtdlIPC *ipc);
-void download_to_local_disk(CtdlIPC *ipc, char *, long);
 void hit_any_key(void);
+int save_buffer(void *file, size_t filelen, const char *pathname);
+void destination_directory(char *dest, const char *supplied_filename);
 
 
 /* 
index fd96cbaeacfff21aa8fc851dc4131b062a1fa6c7..7c44fc566c0a88b06a91a0976a844a07814db807 100644 (file)
@@ -390,26 +390,23 @@ char *strerror(int e)
 
 void progress(long int curr, long int cmax)
 {
-       static long dots_printed;
+       static char dots[] =
+               "**************************************************";
+       char dots_printed[51];
+       char fmt[42];
        long a;
 
-       if (curr==0) {
-               scr_printf(".......................................");
-               scr_printf(".......................................\r");
-               scr_flush();
-               dots_printed = 0;
-       }
-       else if (curr==cmax) {
-               scr_printf("\r%79s\n","");
-       }
-       else {
-               a=(curr * 100) / cmax;
-               a=a*78; a=a/100;
-               while (dots_printed < a) {
-                       scr_printf("*");
-                       ++dots_printed;
-                       scr_flush();
-               }
+       if (curr >= cmax) {
+               sln_printf("\r%79s\r","");
+       } else {
+               /* a will be range 0-50 rather than 0-100 */
+               a=(curr * 50) / cmax;
+               sprintf(fmt, "[%%s%%%lds] %%3ld%%%% %%10ld/%%10ld\r", 50 - a);
+               strncpy(dots_printed, dots, a);
+               dots_printed[a] = 0;
+               sln_printf(fmt, dots_printed, "",
+                               curr * 100 / cmax, curr, cmax);
+               sln_flush();
        }
 }