Add a rfc2045_mimepos_flags() function superset of rfc2045_mimepos()

Adapt dofetchmsgbody, dofetchheadersbuf, dofetchheadersfile,
rfc822, rfc822text to only take lines with LF ending into account
when computing the length and adding CRs
---
 imap/fetch.c      |   80 ++++++++++++++++++++++++++++++-----------------------
 rfc2045/rfc2045.c |   61 ++++++++++++++++++++++++++++------------
 rfc2045/rfc2045.h |   12 ++++++--
 3 files changed, 99 insertions(+), 54 deletions(-)

diff --git a/imap/fetch.c b/imap/fetch.c
index 40dd270..8eaaf8f 100644
--- a/imap/fetch.c
+++ b/imap/fetch.c
@@ -572,14 +572,14 @@ static void rfc822size(FILE *fp, struct fetchinfo *fi,
        struct rfc2045 *mimep)
 {
 off_t start_pos, end_pos, start_body;
-off_t nlines, nbodylines;
+off_t nlflines, nlfbodylines;
 
        writes("RFC822.SIZE ");
 
-       rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
-               &nlines, &nbodylines);
+       rfc2045_mimepos_flags(mimep, &start_pos, &end_pos, &start_body,
+               &nlflines, &nlfbodylines, RFC2045_MIMEPOS_LF_LINES);
 
-       writen(end_pos - start_pos + nlines);
+       writen(end_pos - start_pos + nlflines);
 }
 
 static void all(FILE *fp, struct fetchinfo *fi,
@@ -676,12 +676,13 @@ static void dofetchmsgbody(FILE *fp, struct fetchinfo *fi,
 {
 const char *p=fi->bodysection;
 off_t start_pos, end_pos, start_body;
-off_t nlines, nbodylines;
+off_t nlflines, nlfbodylines;
 unsigned long cnt;
 char   buf[BUFSIZ];
 char   rbuf[BUFSIZ];
 char   *rbufptr;
 int    rbufleft;
+int last, c;
 unsigned long bufptr;
 unsigned long skipping;
 int    ismsgrfc822=1;
@@ -776,19 +777,19 @@ off_t cache_phys_chars;
                return;
        }
 
-       rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
-               &nlines, &nbodylines);
+       rfc2045_mimepos_flags(mimep, &start_pos, &end_pos, &start_body,
+               &nlflines, &nlfbodylines, RFC2045_MIMEPOS_LF_LINES);
 
 
        if (p && strcmp(p, "TEXT") == 0)
        {
                start_seek_pos=start_body;
-               cnt=end_pos - start_body + nbodylines;
+               cnt=end_pos - start_body + nlfbodylines;
        }
        else if (p && strcmp(p, "HEADER") == 0)
        {
                start_seek_pos=start_pos;
-               cnt= start_body - start_pos + (nlines - nbodylines);
+               cnt= start_body - start_pos + (nlflines - nlfbodylines);
        }
        else if (p && strcmp(p, "HEADER.FIELDS") == 0)
        {
@@ -824,13 +825,13 @@ off_t cache_phys_chars;
        {
                start_seek_pos=start_pos;
 
-               cnt= end_pos - start_pos + nlines;
+               cnt= end_pos - start_pos + nlflines;
        }
        else    /* Last possibility: entire body */
        {
                start_seek_pos=start_body;
 
-               cnt= end_pos - start_body + nbodylines;
+               cnt= end_pos - start_body + nlfbodylines;
        }
 
        skipping=0;
@@ -880,10 +881,9 @@ off_t cache_phys_chars;
        rbufptr=0;
        rbufleft=0;
 
+       c=0;
        while (cnt)
        {
-       int     c;
-
                if (!rbufleft)
                {
                        rbufleft=fread(rbuf, 1, sizeof(rbuf), fp);
@@ -898,10 +898,11 @@ off_t cache_phys_chars;
                }
 
                --rbufleft;
+               last=c;
                c=(int)(unsigned char)*rbufptr++;
                ++cnt_phys_chars;
 
-               if (c == '\n')
+               if (c == '\n' && last != '\r')
                {
                        ++cnt_virtual_chars;
 
@@ -1002,7 +1003,7 @@ static void dofetchheadersbuf(FILE *fp, struct fetchinfo 
*fi,
        int (*headerfunc)(struct fetchinfo *fi, const char *))
 {
 off_t start_pos, end_pos, start_body;
-off_t nlines, nbodylines;
+off_t nlflines, nlfbodylines;
 size_t i,j,k,l;
 char   buf[BUFSIZ+2];
 int    goodheader;
@@ -1011,8 +1012,8 @@ unsigned long cnt;
 char   *p;
 int    ii;
 
-       rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
-               &nlines, &nbodylines);
+       rfc2045_mimepos_flags(mimep, &start_pos, &end_pos, &start_body,
+               &nlflines, &nlfbodylines, RFC2045_MIMEPOS_LF_LINES);
        if (fseek(fp, start_pos, SEEK_SET) == -1)
        {
                writes("{0}\r\n");
@@ -1089,7 +1090,7 @@ int       ii;
        p=buf;
        while (skipping)
        {
-               if (*p == '\n')
+               if (*p == '\n' && (p == buf || p[-1] != '\r'))
                {
                        --skipping;
                        if (skipping == 0)
@@ -1110,8 +1111,11 @@ int      ii;
        {
                if (*p == '\n')
                {
-                       writes("\r");
-                       if (--cnt == 0) break;
+                       if (p == buf || p[-1] != '\r')
+                       {
+                               writes("\r");
+                               if (--cnt == 0) break;
+                       }
                        writes("\n");
                        --cnt;
                        ++p;
@@ -1142,9 +1146,9 @@ static void dofetchheadersfile(FILE *fp, struct fetchinfo 
*fi,
        int (*headerfunc)(struct fetchinfo *fi, const char *))
 {
 off_t start_pos, end_pos, start_body, left;
-off_t nlines, nbodylines;
+off_t nlflines, nlfbodylines;
 size_t i;
-int    c, pass;
+int    c, last, pass;
 char   buf1[256];
 int    goodheader;
 struct fetchheaderinfo finfo;
@@ -1155,8 +1159,8 @@ struct    fetchheaderinfo finfo;
        void (*func)(struct fetchheaderinfo *, const char *, size_t)=
                        pass ? printheader:countheader;
 
-               rfc2045_mimepos(mimep, &start_pos, &end_pos, &start_body,
-                       &nlines, &nbodylines);
+               rfc2045_mimepos_flags(mimep, &start_pos, &end_pos, &start_body,
+                       &nlflines, &nlfbodylines, RFC2045_MIMEPOS_LF_LINES);
                if (fseek(fp, start_pos, SEEK_SET) == -1)
                {
                        writes("{0}\r\n");
@@ -1232,6 +1236,7 @@ struct    fetchheaderinfo finfo;
                        i=0;
                        while (left)
                        {
+                               last=c;
                                c=getc(fp);
                                if (c == EOF)
                                {
@@ -1244,7 +1249,7 @@ struct    fetchheaderinfo finfo;
                                        (*func)(&finfo, buf1, i);
                                        i=0;
                                }
-                               if (c == '\n')
+                               if (c == '\n' && last != '\r')
                                {
                                        (*func)(&finfo, buf1, i);
                                        buf1[0]='\r';
@@ -1293,7 +1298,7 @@ static void rfc822(FILE *fp, struct fetchinfo *fi,
        struct rfc2045 *rfcp)
 {
 unsigned long n=0;
-int    c;
+int    c, last;
 char   buf[BUFSIZ];
 unsigned long i;
 
@@ -1305,10 +1310,11 @@ unsigned long i;
                writes("{0}\r\n");
                return;
        }
-       while ((c=getc(fp)) != EOF)
+       c=0;
+       while (last=c, (c=getc(fp)) != EOF)
        {
                ++n;
-               if (c == '\n')  ++n;
+               if (c == '\n' && last != '\r')  ++n;
        }
 
        if (fseek(fp, 0L, SEEK_SET) == -1)
@@ -1322,10 +1328,12 @@ unsigned long i;
        writes("}\r\n");
 
        i=0;
+       c=0;
        while (n)
        {
+               last=c;
                c=getc(fp);
-               if (c == '\n')
+               if (c == '\n' && last != '\r')
                {
                        if (i >= sizeof(buf))
                        {
@@ -1435,16 +1443,16 @@ static void rfc822text(FILE *fp, struct fetchinfo *fi,
        struct rfc2045 *rfcp)
 {
 off_t start_pos, end_pos, start_body;
-off_t nlines, nbodylines;
+off_t nlflines, nlfbodylines;
 unsigned long i;
-int    c;
+int    c, last;
 char   buf[BUFSIZ];
 unsigned long l;
 
        writes("RFC822.TEXT {");
 
-       rfc2045_mimepos(rfcp, &start_pos, &end_pos, &start_body,
-               &nlines, &nbodylines);
+       rfc2045_mimepos_flags(rfcp, &start_pos, &end_pos, &start_body,
+               &nlflines, &nlfbodylines, RFC2045_MIMEPOS_LF_LINES);
 
        if (fseek(fp, start_body, SEEK_SET) == -1)
        {
@@ -1453,14 +1461,16 @@ unsigned long l;
                return;
        }
 
-       i=end_pos - start_body + nbodylines;
+       i=end_pos - start_body + nlfbodylines;
 
        writen(i);
        writes("}\r\n");
 
        l=0;
+       c=0;
        while (i)
        {
+               last=c;
                c=getc(fp);
                if (c == EOF)
                {
@@ -1473,7 +1483,7 @@ unsigned long l;
                        writemem(buf, l);
                        l=0;
                }
-               if (c == '\n' && i)
+               if (c == '\n' && i && last != '\r')
                {
                        --i;
                        buf[l++]='\r';
diff --git a/rfc2045/rfc2045.c b/rfc2045/rfc2045.c
index 2245f43..40c5774 100644
--- a/rfc2045/rfc2045.c
+++ b/rfc2045/rfc2045.c
@@ -238,15 +238,19 @@ static void set_string(char **p,
 /* Update byte counts for this structure, and all the superstructures */
 
 static void update_counts(struct rfc2045 *p, size_t newcnt, size_t newendcnt,
-       unsigned nlines)
+       unsigned nlflines, unsigned ncrlflines)
 {
        while (p)
        {
                p->endpos = newcnt;
                p->endbody = newendcnt;
-               p->nlines += nlines;
+               p->nlflines += nlflines;
+               p->ncrlflines += ncrlflines;
                if (!p->workinheader)
-                       p->nbodylines += nlines;
+               {
+                       p->nlfbodylines += nlflines;
+                       p->ncrlfbodylines += ncrlflines;
+               }
                p=p->parent;
        }
 }
@@ -326,7 +330,7 @@ void rfc2045_parse_partial(struct rfc2045 *h)
                        (!p->lastpart || !p->lastpart->workclosed))
                        (*h->rfc2045acptr->section_contents)(h->workbuf, l);
 
-               update_counts(p, p->endpos+l, p->endpos+l, 0);
+               update_counts(p, p->endpos+l, p->endpos+l, 0, 0);
                p->informdata=1;
                for (i=0; l<h->workbuflen; l++)
                        h->workbuf[i++]=h->workbuf[l];
@@ -403,7 +407,7 @@ size_t      n=cnt-1;        /* Strip \n (we always get at 
least a \n here) */
 struct rfc2045 *newp;
 struct rfc2045ac *rwp=p->rfc2045acptr;
 unsigned num_levels=0;
-
+unsigned iscrlf=0;
 size_t k;
 int    bit8=0;
 
@@ -421,7 +425,10 @@ int        bit8=0;
        }
 
        if (n && c[n-1] == '\r')        /* Strip trailing \r */
+       {
                --n;
+               iscrlf=1;
+       }
 
        /* Before the main drill down loop before, look ahead and see if we're
        ** in a middle of a form-data section.  */
@@ -452,7 +459,7 @@ int bit8=0;
 
                if (p->lastpart->workclosed)
                {
-                       update_counts(p, p->endpos+cnt, p->endpos+n, 1);
+                       update_counts(p, p->endpos+cnt, p->endpos+n, !iscrlf, 
iscrlf);
                        return;
                }
                /* Leftover trash -- workclosed is set when the final
@@ -488,14 +495,14 @@ int       bit8=0;
 
                                p->lastpart->workclosed=1;
                                update_counts(p, p->endpos+cnt, p->endpos+cnt,
-                                       1);
+                                       !iscrlf, iscrlf);
                                return;
                        }
 
                /* Create new RFC2045 section */
 
                        newp=append_part(p, p->endpos+cnt);
-                       update_counts(p, p->endpos+cnt, p->endpos+n, 1);
+                       update_counts(p, p->endpos+cnt, p->endpos+n, !iscrlf, 
iscrlf);
 
                        /* The new RFC2045 section is MIME compliant */
 
@@ -541,7 +548,7 @@ int bit8=0;
                                (*rwp->section_contents)(c, cnt);
 
                        update_counts(p, p->endpos+cnt, p->endpos+cnt_update,
-                               1);
+                               !iscrlf, iscrlf);
                }
                return;
        }
@@ -559,13 +566,13 @@ int       bit8=0;
        if ( n == 0 )   /* End of header, body begins.  Parse header. */
        {
                do_header(p);   /* Clean up any left over header line */
-               p->workinheader=0;
 
                /* Message body starts right here */
 
                p->startbody=p->endpos+cnt;
-               update_counts(p, p->startbody, p->startbody, 1);
-               --p->nbodylines;        /* Don't count the blank line */
+               update_counts(p, p->startbody, p->startbody, !iscrlf, iscrlf);
+
+               p->workinheader=0;
 
                /* Discard content type and boundary if I don't understand
                ** this MIME flavor.
@@ -650,7 +657,7 @@ int bit8=0;
 
        /* RFC822 header continues */
 
-       update_counts(p, p->endpos + cnt, p->endpos+n, 1);
+       update_counts(p, p->endpos + cnt, p->endpos+n, !iscrlf, iscrlf);
 
        /* If this header line starts with a space, append one space
        ** to the saved contents of the previous line, and append this
@@ -1281,15 +1288,27 @@ const char *rfc2045_content_md5(const struct rfc2045 *p)
        return (p->content_md5 ? p->content_md5:"");
 }
 
-void rfc2045_mimepos(const struct rfc2045 *p,
+void rfc2045_mimepos_flags(const struct rfc2045 *p,
        off_t *start_pos, off_t *end_pos, off_t *start_body,
-       off_t *nlines, off_t *nbodylines)
+       off_t *nlines, off_t *nbodylines, int flags)
 {
        *start_pos=p->startpos;
        *end_pos=p->endpos;
 
-       *nlines=p->nlines;
-       *nbodylines=p->nbodylines;
+       *nlines=0;
+       *nbodylines=0;
+       
+       if (flags & RFC2045_MIMEPOS_LF_LINES)
+       {
+               *nlines+=p->nlflines;
+               *nbodylines+=p->nlfbodylines;
+       }
+       if (flags & RFC2045_MIMEPOS_CRLF_LINES)
+       {
+               *nlines+=p->ncrlflines;
+               *nbodylines+=p->ncrlfbodylines;
+       }
+
        if (p->parent)  /* MIME parts do not have the trailing CRLF */
        {
                *end_pos=p->endbody;
@@ -1304,6 +1323,14 @@ void rfc2045_mimepos(const struct rfc2045 *p,
        }
 }
 
+void rfc2045_mimepos(const struct rfc2045 *p,
+       off_t *start_pos, off_t *end_pos, off_t *start_body,
+       off_t *nlines, off_t *nbodylines)
+{
+       rfc2045_mimepos_flags(p, start_pos, end_pos, start_body, 
+               nlines, nbodylines, RFC2045_MIMEPOS_ALL_LINES);
+}
+
 unsigned rfc2045_mimepartcount(const struct rfc2045 *p)
 {
 const struct rfc2045 *q;
diff --git a/rfc2045/rfc2045.h b/rfc2045/rfc2045.h
index ddfab1f..7739757 100644
--- a/rfc2045/rfc2045.h
+++ b/rfc2045/rfc2045.h
@@ -34,8 +34,10 @@ struct rfc2045 {
                endpos,         /* Where it ends */
                startbody,      /* Where the body of the msg starts */
                endbody;        /* endpos - trailing CRLF terminator */
-       off_t   nlines;         /* Number of lines in message */
-       off_t   nbodylines;     /* Number of lines only in the body */
+       off_t   nlflines;               /* Number of lines in message with LF 
line ending */
+       off_t   nlfbodylines;   /* Number of lines only in the body with LF 
line ending */
+       off_t   ncrlflines;             /* Number of lines in message with CRLF 
line ending */
+       off_t   ncrlfbodylines; /* Number of lines only in the body with CRLF 
line ending */
        char *mime_version;
        char *content_type;
        struct rfc2045attr *content_type_attr;  /* Content-Type: attributes */
@@ -119,8 +121,14 @@ const char *rfc2045_content_description(const struct 
rfc2045 *);
 const char *rfc2045_content_language(const struct rfc2045 *);
 const char *rfc2045_content_md5(const struct rfc2045 *);
 
+#define RFC2045_MIMEPOS_LF_LINES 1
+#define RFC2045_MIMEPOS_CRLF_LINES 2
+#define RFC2045_MIMEPOS_ALL_LINES 3
+
 void rfc2045_mimepos(const struct rfc2045 *, off_t *, off_t *, off_t *,
        off_t *, off_t *);
+void rfc2045_mimepos_flags(const struct rfc2045 *, off_t *, off_t *, off_t *,
+       off_t *, off_t *,int);
 unsigned rfc2045_mimepartcount(const struct rfc2045 *);
 
 void rfc2045_xdump(struct rfc2045 *);
-- 
1.7.10.4

------------------------------------------------------------------------------
Slashdot TV.  
Video for Nerds.  Stuff that matters.
http://tv.slashdot.org/
_______________________________________________
Courier-imap mailing list
Courier-imap@lists.sourceforge.net
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/courier-imap

Reply via email to