* msgbase.c: fixed a buffer overflow error
authorArt Cancro <ajc@citadel.org>
Wed, 2 Mar 2005 17:33:03 +0000 (17:33 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 2 Mar 2005 17:33:03 +0000 (17:33 +0000)
* imap_fetch.c, serv_imap.c, serv_imap.h: migrated imap_fetch_rfc822() to
  use the new in-memory message buffering.  BODY comes next...

citadel/ChangeLog
citadel/imap_fetch.c
citadel/msgbase.c
citadel/serv_imap.c
citadel/serv_imap.h

index f592bfee05bc071692304ef9e007e31013d9a3db..9a7f21a94bda455fb904c13d7c105246890ef356 100644 (file)
@@ -1,4 +1,9 @@
  $Log$
+ Revision 641.15  2005/03/02 17:33:03  ajc
+ * msgbase.c: fixed a buffer overflow error
+ * imap_fetch.c, serv_imap.c, serv_imap.h: migrated imap_fetch_rfc822() to
+   use the new in-memory message buffering.  BODY comes next...
+
  Revision 641.14  2005/03/02 03:35:18  ajc
  * serv_smtp.c: removed use of temporary file for SMTP transmission
 
@@ -6479,4 +6484,3 @@ 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 a2e557bb721a769eb7dfbdd405f652aed64fc2a3..e0461a1b8fd10b0d542ac8cb0db2b1444f53b48f 100644 (file)
@@ -121,99 +121,91 @@ void imap_fetch_internaldate(struct CtdlMessage *msg) {
 void imap_fetch_rfc822(long msgnum, char *whichfmt) {
        char buf[SIZ];
        char *ptr;
-       long headers_size, text_size, total_size;
-       long bytes_remaining = 0;
-       long blocksize;
-       FILE *tmp = NULL;
+       size_t headers_size, text_size, total_size;
+       size_t bytes_to_send;
 
        /* Cache the most recent RFC822 FETCH because some clients like to
         * fetch in pieces, and we don't want to have to go back to the
         * message store for each piece.
         */
-       if ((IMAP->cached_fetch != NULL) && (IMAP->cached_msgnum == msgnum)) {
+       if ((IMAP->cached_rfc822_data != NULL)
+          && (IMAP->cached_rfc822_msgnum == msgnum)) {
                /* Good to go! */
-               tmp = IMAP->cached_fetch;
        }
-       else if (IMAP->cached_fetch != NULL) {
+       else if (IMAP->cached_rfc822_data != NULL) {
                /* Some other message is cached -- free it */
-               fclose(IMAP->cached_fetch);
-               IMAP->cached_fetch == NULL;
-               IMAP->cached_msgnum = (-1);
+               free(IMAP->cached_rfc822_data);
+               IMAP->cached_rfc822_data = NULL;
+               IMAP->cached_rfc822_msgnum = (-1);
+               IMAP->cached_rfc822_len = 0;
        }
 
        /* At this point, we now can fetch and convert the message iff it's not
         * the one we had cached.
         */
-       if (tmp == NULL) {
-               tmp = tmpfile();
-               if (tmp == NULL) {
-                       lprintf(CTDL_CRIT, "Cannot open temp file: %s\n",
-                                       strerror(errno));
-                       return;
-               }
-       
+       if (IMAP->cached_rfc822_data == NULL) {
                /*
-                * Load the message into a temp file for translation
-                * and measurement
+                * Load the message into memory for translation & measurement
                 */
-               CtdlRedirectOutput(tmp);
+               CC->redirect_buffer = malloc(SIZ);
+               CC->redirect_len = 0;
+               CC->redirect_alloc = SIZ;
                CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1);
-               CtdlRedirectOutput(NULL);
-
-               IMAP->cached_fetch = tmp;
-               IMAP->cached_msgnum = msgnum;
+               IMAP->cached_rfc822_data = CC->redirect_buffer;
+               IMAP->cached_rfc822_len = CC->redirect_len;
+               IMAP->cached_rfc822_msgnum = msgnum;
+               CC->redirect_buffer = NULL;
+               CC->redirect_len = 0;
+               CC->redirect_alloc = 0;
        }
 
        /*
         * Now figure out where the headers/text break is.  IMAP considers the
         * intervening blank line to be part of the headers, not the text.
         */
-       rewind(tmp);
-       headers_size = 0L;
+       headers_size = 0;
+       text_size = 0;
+       total_size = 0;
+
+       ptr = IMAP->cached_rfc822_data;
        do {
-               ptr = fgets(buf, sizeof buf, tmp);
+               ptr = memreadline(ptr, buf, sizeof buf);
                if (ptr != NULL) {
                        striplt(buf);
                        if (strlen(buf) == 0) {
-                               headers_size = ftell(tmp);
+                               headers_size = ptr - IMAP->cached_rfc822_data;
                        }
                }
-       } while ( (headers_size == 0L) && (ptr != NULL) );
-       fseek(tmp, 0L, SEEK_END);
-       total_size = ftell(tmp);
+       } while ( (headers_size == 0) && (ptr != NULL) );
+
+       total_size = IMAP->cached_rfc822_len;
        text_size = total_size - headers_size;
-       /* lprintf(CTDL_DEBUG, "RFC822: headers=%ld, text=%ld, total=%ld\n",
-               headers_size, text_size, total_size); */
+
+       lprintf(CTDL_DEBUG, "RFC822: headers=%d, text=%d, total=%d\n",
+               headers_size, text_size, total_size);
 
        if (!strcasecmp(whichfmt, "RFC822.SIZE")) {
-               cprintf("RFC822.SIZE %ld", total_size);
+               cprintf("RFC822.SIZE %d", total_size);
                return;
        }
 
        else if (!strcasecmp(whichfmt, "RFC822")) {
-               bytes_remaining = total_size;
-               rewind(tmp);
+               ptr = IMAP->cached_rfc822_data;
+               bytes_to_send = total_size;
        }
 
        else if (!strcasecmp(whichfmt, "RFC822.HEADER")) {
-               bytes_remaining = headers_size;
-               rewind(tmp);
+               ptr = IMAP->cached_rfc822_data;
+               bytes_to_send = headers_size;
        }
 
        else if (!strcasecmp(whichfmt, "RFC822.TEXT")) {
-               bytes_remaining = text_size;
-               fseek(tmp, headers_size, SEEK_SET);
-       }
-
-       cprintf("%s {%ld}\r\n", whichfmt, bytes_remaining);
-       blocksize = (long)sizeof(buf);
-       while (bytes_remaining > 0L) {
-               if (blocksize > bytes_remaining) blocksize = bytes_remaining;
-               fread(buf, (size_t)blocksize, 1, tmp);
-               client_write(buf, (int)blocksize);
-               bytes_remaining = bytes_remaining - blocksize;
+               ptr = &IMAP->cached_rfc822_data[headers_size];
+               bytes_to_send = text_size;
        }
 
+       cprintf("%s {%d}\r\n", whichfmt, bytes_to_send);
+       client_write(ptr, bytes_to_send);
 }
 
 
index 08ee1d1f5a936ead658a624f7e95da0565153faa..2aaf88e2326f12167dce2f7a2ccccbbfd27da389 100644 (file)
@@ -1959,9 +1959,11 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,      /* message to save */
                break;
        case 4:
                strcpy(content_type, "text/plain");
-               mptr = bmstrstr(msg->cm_fields['M'], "Content-type: ", strncasecmp);
+               mptr = bmstrstr(msg->cm_fields['M'],
+                               "Content-type: ", strncasecmp);
                if (mptr != NULL) {
-                       strcpy(content_type, &mptr[14]);
+                       safestrncpy(content_type, &mptr[14], 
+                                       sizeof content_type);
                        for (a = 0; a < strlen(content_type); ++a) {
                                if ((content_type[a] == ';')
                                    || (content_type[a] == ' ')
@@ -1974,7 +1976,8 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
        }
 
        /* Goto the correct room */
-       lprintf(CTDL_DEBUG, "Selected room %s\n", (recps) ? CC->room.QRname : SENTITEMS);
+       lprintf(CTDL_DEBUG, "Selected room %s\n",
+               (recps) ? CC->room.QRname : SENTITEMS);
        strcpy(hold_rm, CC->room.QRname);
        strcpy(actual_rm, CC->room.QRname);
        if (recps != NULL) {
index afa0df36021c86b1ac4deb2fc23d1e28983d3c21..f98352af4a64f603d7d7b14399e5904053b5f0a5 100644 (file)
@@ -331,10 +331,10 @@ void imap_cleanup_function(void)
        imap_free_msgids();
        imap_free_transmitted_message();
 
-       if (IMAP->cached_fetch != NULL) {
-               fclose(IMAP->cached_fetch);
-               IMAP->cached_fetch = NULL;
-               IMAP->cached_msgnum = (-1);
+       if (IMAP->cached_rfc822_data != NULL) {
+               free(IMAP->cached_rfc822_data);
+               IMAP->cached_rfc822_data = NULL;
+               IMAP->cached_rfc822_msgnum = (-1);
        }
 
        if (IMAP->cached_body != NULL) {
@@ -357,8 +357,8 @@ void imap_greeting(void)
        strcpy(CC->cs_clientname, "IMAP session");
        CtdlAllocUserData(SYM_IMAP, sizeof(struct citimap));
        IMAP->authstate = imap_as_normal;
-       IMAP->cached_fetch = NULL;
-       IMAP->cached_msgnum = (-1);
+       IMAP->cached_rfc822_data = NULL;
+       IMAP->cached_rfc822_msgnum = (-1);
 
        cprintf("* OK %s Citadel IMAP4rev1 server ready\r\n",
                config.c_fqdn);
index f20027cbaf488e9d4d77a545dd396d251e0ad487..3a7762be4a1c85e3ed4bda6b0e15a6b193b00da7 100644 (file)
@@ -21,8 +21,10 @@ struct citimap {
        char *transmitted_message;      /* for APPEND command... */
        size_t transmitted_length;
 
-       FILE *cached_fetch;             /* cache our most recent RFC822 FETCH */
-       long cached_msgnum;             /* because the client might ask for it in pieces */
+       /* Cache most recent RFC822 FETCH because client might load in pieces */
+       char *cached_rfc822_data;
+       long cached_rfc822_msgnum;
+       size_t cached_rfc822_len;
 
        FILE *cached_body;              /* cache our most recent BODY FETCH */
        char cached_bodypart[SIZ];      /* because the client might ask for it in pieces */