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 | 75 +++++++++++++++++++++++++++++------------------------
rfc2045/rfc2045.c | 61 +++++++++++++++++++++++++++++++------------
rfc2045/rfc2045.h | 12 +++++++--
3 files changed, 95 insertions(+), 53 deletions(-)
diff --git a/imap/fetch.c b/imap/fetch.c
index 40dd270..af6652e 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)
@@ -1108,7 +1109,7 @@ int ii;
while (cnt)
{
- if (*p == '\n')
+ if (*p == '\n' && (p == buf || p[-1] != '\r'))
{
writes("\r");
if (--cnt == 0) break;
@@ -1142,9 +1143,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 +1156,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 +1233,7 @@ struct fetchheaderinfo finfo;
i=0;
while (left)
{
+ last=c;
c=getc(fp);
if (c == EOF)
{
@@ -1244,7 +1246,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 +1295,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 +1307,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 +1325,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 +1440,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 +1458,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 +1480,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
[email protected]
Unsubscribe: https://lists.sourceforge.net/lists/listinfo/courier-imap