]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Partial fetches were broken when they stopped between virtual CR and LF.
authorTimo Sirainen <tss@iki.fi>
Sat, 26 Apr 2003 21:52:38 +0000 (00:52 +0300)
committerTimo Sirainen <tss@iki.fi>
Sat, 26 Apr 2003 21:52:38 +0000 (00:52 +0300)
--HG--
branch : HEAD

src/imap/imap-fetch-body-section.c
src/imap/imap-fetch.c
src/lib-mail/message-send.c
src/lib-mail/message-send.h
src/lib-mail/message-size.c
src/lib-mail/message-size.h

index c68702c6cb9eeb92733f1dcd174d9bf28defec3c..97d365a5b5cb75d5932a2fde342b654a8338b5d4 100644 (file)
@@ -34,10 +34,11 @@ struct partial_cache {
        unsigned int uid;
 
        uoff_t physical_start;
+       int cr_skipped;
        struct message_size pos;
 };
 
-static struct partial_cache partial = { 0, 0, 0, { 0, 0, 0 } };
+static struct partial_cache partial = { 0, 0, 0, 0, { 0, 0, 0 } };
 
 static int seek_partial(unsigned int select_counter, unsigned int uid,
                        struct partial_cache *partial, struct istream *stream,
@@ -59,11 +60,10 @@ static int seek_partial(unsigned int select_counter, unsigned int uid,
 
        i_stream_seek(stream, partial->physical_start +
                      partial->pos.physical_size);
-       message_skip_virtual(stream, virtual_skip, &partial->pos, &cr_skipped);
-
-       if (cr_skipped)
-               partial->pos.virtual_size--;
+       message_skip_virtual(stream, virtual_skip, &partial->pos,
+                            partial->cr_skipped, &cr_skipped);
 
+       partial->cr_skipped = FALSE;
        return cr_skipped;
 }
 
@@ -75,7 +75,7 @@ static int fetch_body(struct imap_fetch_context *ctx,
        struct message_size hdr_size, body_size;
        struct istream *stream;
        const char *str;
-       int skip_cr;
+       int skip_cr, last_cr;
        uoff_t size;
        off_t ret;
 
@@ -102,8 +102,9 @@ static int fetch_body(struct imap_fetch_context *ctx,
                               body->skip);
 
        ret = message_send(ctx->output, stream, &body_size,
-                          skip_cr, body->max_size);
+                          skip_cr, body->max_size, &last_cr);
        if (ret > 0) {
+               partial.cr_skipped = last_cr != 0;
                partial.pos.physical_size =
                        stream->v_offset - partial.physical_start;
                partial.pos.virtual_size += ret;
@@ -287,7 +288,7 @@ static int fetch_header_from(struct imap_fetch_context *ctx,
                if (o_stream_send_str(ctx->output, str) < 0)
                        return FALSE;
                return message_send(ctx->output, input, size,
-                                   body->skip, body->max_size) >= 0;
+                                   body->skip, body->max_size, NULL) >= 0;
        }
 
        /* partial headers - copy the wanted fields into memory, inserting
@@ -418,7 +419,7 @@ static int fetch_part_body(struct imap_fetch_context *ctx,
                           struct mail *mail, const struct message_part *part)
 {
        const char *str;
-       int skip_cr;
+       int skip_cr, last_cr;
        uoff_t size;
        off_t ret;
 
@@ -436,8 +437,9 @@ static int fetch_part_body(struct imap_fetch_context *ctx,
                               &partial, stream, part->physical_pos +
                               part->header_size.physical_size, body->skip);
        ret = message_send(ctx->output, stream, &part->body_size,
-                          skip_cr, body->max_size);
+                          skip_cr, body->max_size, &last_cr);
        if (ret > 0) {
+               partial.cr_skipped = last_cr != 0;
                partial.pos.physical_size =
                        stream->v_offset - partial.physical_start;
                partial.pos.virtual_size += ret;
index fa847aa2369748df0f66ee9ac6e0c6ee8f6b9d8e..66e61a656fcc2133be393689c887e344c6a2598f 100644 (file)
@@ -113,7 +113,7 @@ static int fetch_send_rfc822(struct imap_fetch_context *ctx, struct mail *mail)
                return FALSE;
 
        return message_send(ctx->output, stream, &body_size,
-                           0, (uoff_t)-1) >= 0;
+                           0, (uoff_t)-1, NULL) >= 0;
 }
 
 static int fetch_send_rfc822_header(struct imap_fetch_context *ctx,
@@ -135,7 +135,8 @@ static int fetch_send_rfc822_header(struct imap_fetch_context *ctx,
        if (o_stream_send_str(ctx->output, str) < 0)
                return FALSE;
 
-       return message_send(ctx->output, stream, &hdr_size, 0, (uoff_t)-1) >= 0;
+       return message_send(ctx->output, stream, &hdr_size,
+                           0, (uoff_t)-1, NULL) >= 0;
 }
 
 static int fetch_send_rfc822_text(struct imap_fetch_context *ctx,
@@ -159,7 +160,7 @@ static int fetch_send_rfc822_text(struct imap_fetch_context *ctx,
 
        i_stream_seek(stream, hdr_size.physical_size);
        return message_send(ctx->output, stream, &body_size,
-                           0, (uoff_t)-1) >= 0;
+                           0, (uoff_t)-1, NULL) >= 0;
 }
 
 static int fetch_mail(struct imap_fetch_context *ctx, struct mail *mail)
index 0e4af83ec0aa2ba83823f3f103a40b7a2fb3a2a9..2723ed1e9d3bbeaf86872d53765bd1f8ca5f64ac 100644 (file)
@@ -9,7 +9,7 @@
 
 off_t message_send(struct ostream *output, struct istream *input,
                   const struct message_size *msg_size,
-                  uoff_t virtual_skip, uoff_t max_virtual_size)
+                  uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr)
 {
        const unsigned char *msg;
        uoff_t old_limit, limit;
@@ -17,6 +17,9 @@ off_t message_send(struct ostream *output, struct istream *input,
        off_t ret;
        int cr_skipped, add_cr;
 
+       if (last_cr != NULL)
+               *last_cr = -1;
+
        if (msg_size->physical_size == 0 ||
            virtual_skip >= msg_size->virtual_size)
                return 0;
@@ -37,7 +40,7 @@ off_t message_send(struct ostream *output, struct istream *input,
                return ret;
        }
 
-       message_skip_virtual(input, virtual_skip, NULL, &cr_skipped);
+       message_skip_virtual(input, virtual_skip, NULL, 0, &cr_skipped);
 
        /* go through the message data and insert CRs where needed.  */
        ret = 0;
@@ -73,5 +76,70 @@ off_t message_send(struct ostream *output, struct istream *input,
                i_stream_skip(input, i);
        }
 
+       if (last_cr != NULL)
+               *last_cr = cr_skipped;
        return ret;
 }
+
+void message_skip_virtual(struct istream *input, uoff_t virtual_skip,
+                         struct message_size *msg_size,
+                         int cr_skipped, int *last_cr)
+{
+       const unsigned char *msg;
+       size_t i, size, startpos;
+
+       if (virtual_skip == 0) {
+               *last_cr = cr_skipped;
+               return;
+       }
+
+       *last_cr = FALSE;
+       startpos = 0;
+       while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
+               for (i = startpos; i < size && virtual_skip > 0; i++) {
+                       virtual_skip--;
+
+                       if (msg[i] == '\r') {
+                               /* CR */
+                               if (virtual_skip == 0)
+                                       *last_cr = TRUE;
+                       } else if (msg[i] == '\n') {
+                               /* LF */
+                               if ((i == 0 && !cr_skipped) ||
+                                   (i > 0 && msg[i-1] != '\r')) {
+                                       /* missing CR */
+                                       if (msg_size != NULL)
+                                               msg_size->virtual_size++;
+
+                                       if (virtual_skip == 0) {
+                                               /* CR/LF boundary */
+                                               *last_cr = TRUE;
+                                               break;
+                                       }
+
+                                       virtual_skip--;
+                               }
+
+                               /* increase after making sure we didn't break
+                                  at virtual \r */
+                               if (msg_size != NULL)
+                                       msg_size->lines++;
+                       }
+               }
+
+               if (msg_size != NULL) {
+                       msg_size->physical_size += i;
+                       msg_size->virtual_size += i;
+               }
+
+               if (i < size) {
+                       i_stream_skip(input, i);
+                       break;
+               }
+
+               /* leave the last character, it may be \r */
+               i_stream_skip(input, i - 1);
+               startpos = 1;
+               cr_skipped = FALSE;
+       }
+}
index 942d8fd25f45d44eca9694f4ccb0b4f249942897..1aec82bb1878b8cb15ed9a6c754fdef82acc6633 100644 (file)
@@ -6,10 +6,18 @@ struct message_size;
 /* Send message to client inserting CRs if needed. Only max_virtual_size
    bytes if sent (relative to virtual_skip), if you want it unlimited,
    use (uoff_t)-1. Remember that if input begins with LF, CR is inserted
-   before it unless virtual_skip = 1. Returns number of bytes sent, or -1
-   if error. */
+   before it unless virtual_skip = 1. last_cr is set to 1, 0 or -1 if not
+   known. Returns number of bytes sent, or -1 if error. */
 off_t message_send(struct ostream *output, struct istream *input,
                   const struct message_size *msg_size,
-                  uoff_t virtual_skip, uoff_t max_virtual_size);
+                  uoff_t virtual_skip, uoff_t max_virtual_size, int *last_cr);
+
+/* Skip number of virtual bytes from putfer. msg_size is updated if it's not
+   NULL. If cr_skipped is TRUE and first character is \n, it's not treated as
+   \r\n. last_cr is set to TRUE if last character we skipped was \r, meaning
+   that next character should be \n and you shouldn't treat it as \r\n. */
+void message_skip_virtual(struct istream *input, uoff_t virtual_skip,
+                         struct message_size *msg_size,
+                         int cr_skipped, int *last_cr);
 
 #endif
index 321a9b4cb47d8eccdd7cacb56c375afefb8338f7..09229933c761409d54b094bf206b602a1a72239b 100644 (file)
@@ -110,64 +110,6 @@ void message_get_body_size(struct istream *input, struct message_size *body,
                *last_cr = cr;
 }
 
-void message_skip_virtual(struct istream *input, uoff_t virtual_skip,
-                         struct message_size *msg_size, int *cr_skipped)
-{
-       const unsigned char *msg;
-       size_t i, size, startpos;
-
-       *cr_skipped = FALSE;
-       if (virtual_skip == 0)
-               return;
-
-       startpos = 0;
-       while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
-               for (i = startpos; i < size && virtual_skip > 0; i++) {
-                       virtual_skip--;
-
-                       if (msg[i] == '\r') {
-                               /* CR */
-                               if (virtual_skip == 0)
-                                       *cr_skipped = TRUE;
-                       } else if (msg[i] == '\n') {
-                               /* LF */
-                               if (i == 0 || msg[i-1] != '\r') {
-                                       /* missing CR */
-                                       if (msg_size != NULL)
-                                               msg_size->virtual_size++;
-
-                                       if (virtual_skip == 0) {
-                                               /* CR/LF boundary */
-                                               *cr_skipped = TRUE;
-                                               break;
-                                       }
-
-                                       virtual_skip--;
-                               }
-
-                               /* increase after making sure we didn't break
-                                  at virtual \r */
-                               if (msg_size != NULL)
-                                       msg_size->lines++;
-                       }
-               }
-
-               if (msg_size != NULL) {
-                       msg_size->physical_size += i;
-                       msg_size->virtual_size += i;
-               }
-
-               if (i < size) {
-                       i_stream_skip(input, i);
-                       break;
-               }
-
-               /* leave the last character, it may be \r */
-               i_stream_skip(input, i - 1);
-               startpos = 1;
-       }
-}
-
 void message_size_add(struct message_size *dest,
                      const struct message_size *src)
 {
index b8e2758a6944b6d425a6da01a8673b09b82cbd2c..0c180fb3e33912a4d46e61e5e5166b08801e74a5 100644 (file)
@@ -16,12 +16,6 @@ void message_get_header_size(struct istream *input, struct message_size *hdr);
 void message_get_body_size(struct istream *input, struct message_size *body,
                           uoff_t max_virtual_size, int *last_cr);
 
-/* Skip number of virtual bytes from putfer. If first character is \n, and
-   cr_skipped is FALSE, \r must be sent before it. msg_size is updated if
-   it's not NULL. */
-void message_skip_virtual(struct istream *input, uoff_t virtual_skip,
-                         struct message_size *msg_size, int *cr_skipped);
-
 /* Sum contents of src into dest. */
 void message_size_add(struct message_size *dest,
                      const struct message_size *src);