Keep track of the caller bestenc flags that make sense.

2000-11-08  Not Zed  <NotZed@HelixCode.com>

	* camel-mime-message.c (find_best_encoding): Keep track of the
	caller bestenc flags that make sense.

	* camel-mime-filter-bestenc.c (filter): Added code to detect when
	we have "^From " lines in the sequence of text.
	(camel_mime_filter_bestenc_get_best_encoding): Added a new flag
	CAMEL_BESTENC_NO_FROM: if set, it will not allow any lines
	matching "^From " to appear in the output - currently forcing
	base64 encoding to achieve this.

	* camel-mime-parser.c (folder_scan_step): Call
	camel_mime-filter_complete() once we're done, rather than
	filter_filter().
	(folder_scan_content): Some fixes for state changing; so that when
	we do find another boundary it is properly flagged.  Since we
	strip the last \n off all data, we must take that into account
	too.  Sigh.  Fixes a rather nasty set of bugs where multipart
	messages could start including following messages as parts, etc.
	(struct _header_scan_stack): Added new parameter,
	boundarylenfinal, which holds the length of the final boundary, if
	it is different (e.g. for From lines, whihc aren't)
	(folder_scan_step): Setup teh boundarylenfinal value when creating
	a new boundary.
	(folder_scan_content): Hmm, if we hit the end-of-buffer sentinal,
	reset the scanner back to leave 'atleast' chars in the buffer
	still, dump that content, and retry again.  Stops us losing a
	check for a boundary on some data we haven't really looked at yet!
	(folder_scan_content): Use boundarylenfinal to calculate
	'atleast'.
	(folder_scan_header): And here too.
	(folder_boundary_check): Use the atleast value directly, dont
	truncate it.  Use the boundarylen/boundarylenfinal values directly
	too.
	(struct _header_scan_stack): Add an atleast parameter to cache the
	atleast info.
	(folder_push_part): Determine/set 'atleast', every time we add a
	new part.
	(folder_scan_header): Get the cached atleast info from the current
	part.
	(folder_scan_content): And here too.
	(folder_scan_header): Fix a problem where a part starting with
	" text" would be interpreted as a followon header wrongly.

	* camel-mime-filter-charset.c (complete): Add some assertions to
	find a bug.

svn path=/trunk/; revision=6500
This commit is contained in:
Not Zed
2000-11-08 09:13:52 +00:00
committed by Michael Zucci
parent 18c2d259b2
commit 2b97bd935b
7 changed files with 239 additions and 139 deletions

View File

@ -1,3 +1,51 @@
2000-11-08 Not Zed <NotZed@HelixCode.com>
* camel-mime-message.c (find_best_encoding): Keep track of the
caller bestenc flags that make sense.
* camel-mime-filter-bestenc.c (filter): Added code to detect when
we have "^From " lines in the sequence of text.
(camel_mime_filter_bestenc_get_best_encoding): Added a new flag
CAMEL_BESTENC_NO_FROM: if set, it will not allow any lines
matching "^From " to appear in the output - currently forcing
base64 encoding to achieve this.
* camel-mime-parser.c (folder_scan_step): Call
camel_mime-filter_complete() once we're done, rather than
filter_filter().
(folder_scan_content): Some fixes for state changing; so that when
we do find another boundary it is properly flagged. Since we
strip the last \n off all data, we must take that into account
too. Sigh. Fixes a rather nasty set of bugs where multipart
messages could start including following messages as parts, etc.
(struct _header_scan_stack): Added new parameter,
boundarylenfinal, which holds the length of the final boundary, if
it is different (e.g. for From lines, whihc aren't)
(folder_scan_step): Setup teh boundarylenfinal value when creating
a new boundary.
(folder_scan_content): Hmm, if we hit the end-of-buffer sentinal,
reset the scanner back to leave 'atleast' chars in the buffer
still, dump that content, and retry again. Stops us losing a
check for a boundary on some data we haven't really looked at yet!
(folder_scan_content): Use boundarylenfinal to calculate
'atleast'.
(folder_scan_header): And here too.
(folder_boundary_check): Use the atleast value directly, dont
truncate it. Use the boundarylen/boundarylenfinal values directly
too.
(struct _header_scan_stack): Add an atleast parameter to cache the
atleast info.
(folder_push_part): Determine/set 'atleast', every time we add a
new part.
(folder_scan_header): Get the cached atleast info from the current
part.
(folder_scan_content): And here too.
(folder_scan_header): Fix a problem where a part starting with
" text" would be interpreted as a followon header wrongly.
* camel-mime-filter-charset.c (complete): Add some assertions to
find a bug.
2000-11-07 Ettore Perazzoli <ettore@helixcode.com>
* camel-service.c (get_name): Strdup the "???" string you return,

View File

@ -20,6 +20,8 @@
#include "camel-mime-filter-bestenc.h"
#include <string.h>
static void camel_mime_filter_bestenc_class_init (CamelMimeFilterBestencClass *klass);
static void camel_mime_filter_bestenc_init (CamelMimeFilter *obj);
@ -54,6 +56,10 @@ reset(CamelMimeFilter *mf)
f->total = 0;
f->lastc = ~0;
f->crlfnoorder = FALSE;
f->fromcount = 0;
f->hadfrom = FALSE;
f->startofline = TRUE;
camel_charset_init(&f->charset);
}
@ -63,7 +69,8 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s
CamelMimeFilterBestenc *f = (CamelMimeFilterBestenc *)mf;
register unsigned char *p, *pend;
f->total += len;
if (len == 0)
goto donothing;
if (f->flags & CAMEL_BESTENC_GET_ENCODING) {
register unsigned int /* hopefully reg's are assinged in the order they appear? */
@ -73,6 +80,21 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s
count0=f->count0,
count8 = f->count8;
/* Check ^From lines first call, or have the start of a new line waiting? */
if ((f->flags & CAMEL_BESTENC_NO_FROM) && !f->hadfrom
&& (f->fromcount > 0 || f->startofline)) {
if (f->fromcount + len >=5) {
memcpy(&f->fromsave[f->fromcount], in, 5-f->fromcount);
f->hadfrom = strncmp(f->fromsave, "From ", 5) == 0;
f->fromcount = 0;
} else {
memcpy(&f->fromsave[f->fromcount], in, len);
f->fromcount += len;
}
}
f->startofline = FALSE;
/* See rfc2045 section 2 for definitions of 7bit/8bit/binary */
p = in;
pend = p + len;
@ -98,6 +120,18 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s
if (countline > f->maxline)
f->maxline = countline;
countline = 0;
/* Check for "^From " lines */
if ((f->flags & CAMEL_BESTENC_NO_FROM) && !f->hadfrom) {
if (pend-p >= 5) {
f->hadfrom = strncmp(p, "From ", 5) == 0;
} else if (pend-p == 0) {
f->startofline = TRUE;
} else {
f->fromcount = pend-p;
memcpy(f->fromsave, p, pend-p);
}
}
} else {
f->crlfnoorder = TRUE;
}
@ -112,9 +146,12 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s
f->lastc = lastc;
}
f->total += len;
if (f->flags & CAMEL_BESTENC_GET_CHARSET)
camel_charset_step(&f->charset, in, len);
donothing:
*out = in;
*outlen = len;
*outprespace = prespace;
@ -187,6 +224,12 @@ camel_mime_filter_bestenc_get_best_encoding(CamelMimeFilterBestenc *f, CamelBest
printf(" %d%% require encoding?\n", (f->count0+f->count8)*100 / f->total);
#endif
/* if we're not allowed to have From lines and we had one, use an encoding
that will never let it show. Unfortunately only base64 can at present,
although qp could be modified to allow it too */
if ((f->flags & CAMEL_BESTENC_NO_FROM) && f->hadfrom)
return CAMEL_MIME_PART_ENCODING_BASE64;
/* if we need to encode, see how we do it */
if (required == CAMEL_BESTENC_BINARY)
bestenc = CAMEL_MIME_PART_ENCODING_BINARY;

View File

@ -36,7 +36,9 @@ enum _CamelBestencRequired {
CAMEL_BESTENC_GET_CHARSET = 1<<1,
/* do we treat 'lf' as if it were crlf? */
CAMEL_BESTENC_LF_IS_CRLF = 1<<8
CAMEL_BESTENC_LF_IS_CRLF = 1<<8,
/* do we not allow "From " to appear at the start of a line in any part? */
CAMEL_BESTENC_NO_FROM = 1<<9,
};
typedef enum _CamelBestencRequired CamelBestencRequired;
@ -59,6 +61,12 @@ struct _CamelMimeFilterBestenc {
unsigned int lastc; /* the last character read */
int crlfnoorder; /* if crlf's occured where they shouldn't have */
int startofline; /* are we at the start of a new line? */
int fromcount;
char fromsave[6]; /* save a few characters if we found an \nF near the end of the buffer */
int hadfrom; /* did we encounter a "\nFrom " in the data? */
unsigned int countline; /* current count of characters on a given line */
unsigned int maxline; /* max length of any line */

View File

@ -26,6 +26,7 @@
#include "camel-mime-filter-charset.h"
#define d(x)
static void camel_mime_filter_charset_class_init (CamelMimeFilterCharsetClass *klass);
static void camel_mime_filter_charset_init (CamelMimeFilterCharset *obj);
@ -101,6 +102,9 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out,
outbuf = mf->outbuf;
outlen = mf->outsize;
/* temporary fix to find another bug somewhere */
d(memset(outbuf, 0, outlen));
if (inlen>0) {
converted = unicode_iconv(f->ic, &inbuf, &inlen, &outbuf, &outlen);
if (converted == -1) {
@ -122,6 +126,15 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out,
g_warning("Conversion failed to complete: %s", strerror(errno));
}
/* debugging assertion - check for NUL's in output */
d({
int i;
for (i=0;i<(mf->outsize - outlen);i++) {
g_assert(mf->outbuf[i]);
}
});
*out = mf->outbuf;
*outlenptr = mf->outsize - outlen;
*outprespace = mf->outpre;

View File

@ -583,7 +583,7 @@ find_best_encoding(CamelMimePart *part, CamelBestencRequired required, CamelBest
CamelMimeFilterBestenc *bestenc;
int idb, idc = -1;
gboolean istext;
unsigned int flags;
unsigned int flags, callerflags;
CamelMimePartEncodingType encoding;
CamelDataWrapper *content;
@ -591,7 +591,7 @@ find_best_encoding(CamelMimePart *part, CamelBestencRequired required, CamelBest
not have to read the whole lot into memory - although i have a feeling
it would make things a fair bit simpler to do so ... */
printf("starting to check part\n");
d(printf("starting to check part\n"));
content = camel_medium_get_content_object((CamelMedium *)part);
if (content == NULL) {
@ -610,6 +610,9 @@ find_best_encoding(CamelMimePart *part, CamelBestencRequired required, CamelBest
/* when building the message, any encoded parts are translated already */
flags |= CAMEL_BESTENC_LF_IS_CRLF;
/* and get any flags the caller passed in */
callerflags = (required & CAMEL_BESTENC_NO_FROM);
flags |= callerflags;
/* first a null stream, so any filtering is thrown away; we only want the sideeffects */
null = (CamelStream *)camel_stream_null_new();
@ -628,7 +631,7 @@ find_best_encoding(CamelMimePart *part, CamelBestencRequired required, CamelBest
bestenc = camel_mime_filter_bestenc_new(flags);
idb = camel_stream_filter_add(filter, (CamelMimeFilter *)bestenc);
printf("writing to checking stream\n");
d(printf("writing to checking stream\n"));
camel_data_wrapper_write_to_stream(content, (CamelStream *)filter);
camel_stream_filter_remove(filter, idb);
if (idc != -1) {
@ -640,13 +643,13 @@ find_best_encoding(CamelMimePart *part, CamelBestencRequired required, CamelBest
if (istext)
charsetin = camel_mime_filter_bestenc_get_best_charset(bestenc);
printf("charsetin = %s\n", charsetin);
d(printf("charsetin = %s\n", charsetin));
/* if we have US-ASCII, or we're not doing text, we dont need to bother with the rest */
if (charsetin != NULL && (required & CAMEL_BESTENC_GET_CHARSET) != 0) {
charset = g_strdup(charsetin);
printf("have charset, trying conversion/etc\n");
d(printf("have charset, trying conversion/etc\n"));
/* now the 'bestenc' can has told us what the best encoding is, we can use that to create
a charset conversion filter as well, and then re-add the bestenc to filter the
@ -663,7 +666,7 @@ find_best_encoding(CamelMimePart *part, CamelBestencRequired required, CamelBest
/* otherwise, try another pass, converting to the real charset */
camel_mime_filter_reset((CamelMimeFilter *)bestenc);
camel_mime_filter_bestenc_set_flags(bestenc, CAMEL_BESTENC_GET_ENCODING|CAMEL_BESTENC_LF_IS_CRLF);
camel_mime_filter_bestenc_set_flags(bestenc, CAMEL_BESTENC_GET_ENCODING|CAMEL_BESTENC_LF_IS_CRLF|callerflags);
camel_stream_filter_add(filter, (CamelMimeFilter *)charenc);
camel_stream_filter_add(filter, (CamelMimeFilter *)bestenc);
@ -681,7 +684,7 @@ find_best_encoding(CamelMimePart *part, CamelBestencRequired required, CamelBest
camel_object_unref((CamelObject *)bestenc);
camel_object_unref((CamelObject *)null);
printf("done, best encoding = %d\n", encoding);
d(printf("done, best encoding = %d\n", encoding));
if (charsetp)
*charsetp = charset;
@ -719,7 +722,7 @@ best_encoding(CamelMimeMessage *msg, CamelMimePart *part, void *datap)
gmime_content_field_set_parameter(part->content_type, "charset", charset?charset:"us-ascii");
newct = header_content_type_format(part->content_type->content_type);
if (newct) {
printf("Setting content-type to %s\n", newct);
d(printf("Setting content-type to %s\n", newct));
camel_mime_part_set_content_type(part, newct);
g_free(newct);

View File

@ -260,7 +260,9 @@ struct _header_scan_stack {
int prestage; /* used to determine if it is a pre-boundary or post-boundary data segment */
char *boundary; /* for multipart/ * boundaries, including leading -- and trailing -- for the final part */
int boundarylen; /* length of boundary, including leading -- */
int boundarylen; /* actual length of boundary, including leading -- if there is one */
int boundarylenfinal; /* length of boundary, including trailing -- if there is one */
int atleast; /* the biggest boundary from here to the parent */
};
struct _header_scan_filter {
@ -946,6 +948,11 @@ folder_seek(struct _header_scan_state *s, off_t offset, int whence)
static void
folder_push_part(struct _header_scan_state *s, struct _header_scan_stack *h)
{
if (s->parts && s->parts->atleast > h->boundarylenfinal)
h->atleast = s->parts->atleast;
else
h->atleast = h->boundarylenfinal;
h->parent = s->parts;
s->parts = h;
}
@ -1003,30 +1010,38 @@ folder_scan_skip_line(struct _header_scan_state *s)
s->atleast = atleast;
return -1; /* not found */
}
return -1; /* not found */
}
/* TODO: Is there any way to make this run faster? It gets called a lot ... */
static struct _header_scan_stack *
folder_boundary_check(struct _header_scan_state *s, const char *boundary, int *lastone)
{
struct _header_scan_stack *part;
int len = s->atleast-2; /* make sure we dont access past the buffer */
int len = s->atleast; /* make sure we dont access past the buffer */
h(printf("checking boundary marker upto %d bytes\n", len));
part = s->parts;
while (part) {
h(printf(" boundary: %s\n", part->boundary));
h(printf(" against: '%.*s'\n", len, boundary));
h(printf(" against: '%.*s'\n", s->atleast, boundary));
if (part->boundary
&& part->boundarylen <= len
&& memcmp(boundary, part->boundary, part->boundarylen)==0) {
h(printf("matched boundary: %s\n", part->boundary));
/* again, make sure we're in range */
if (part->boundarylen <= len+2) {
h(printf("checking lastone\n"));
*lastone = (boundary[part->boundarylen]=='-'
&& boundary[part->boundarylen+1]=='-');
if (part->boundarylenfinal <= len) {
int extra = part->boundarylenfinal - part->boundarylen;
/* check the extra stuff on an final boundary, normally -- for mime parts */
if (extra>0) {
*lastone = memcmp(&boundary[part->boundarylen],
&part->boundary[part->boundarylen],
extra) == 0;
} else {
*lastone = TRUE;
}
h(printf("checking lastone = %s\n", *lastone?"TRUE":"FALSE"));
} else {
h(printf("not enough room to check last one?\n"));
*lastone = FALSE;
@ -1045,34 +1060,34 @@ header_append_mempool(struct _header_scan_state *s, struct _header_scan_stack *h
{
struct _header_raw *l, *n;
char *content;
content = strchr(header, ':');
if (content) {
register int len;
n = mempool_alloc(h->pool, sizeof(*n));
n->next = NULL;
len = content-header;
n->name = mempool_alloc(h->pool, len+1);
memcpy(n->name, header, len);
n->name[len] = 0;
content++;
len = s->outptr - content;
n->value = mempool_alloc(h->pool, len+1);
memcpy(n->value, content, len);
n->value[len] = 0;
n->offset = offset;
l = (struct _header_raw *)&h->headers;
while (l->next) {
l = l->next;
}
l->next = n;
}
}
#define header_raw_append_parse(a, b, c) (header_append_mempool(s, h, b, c))
@ -1119,37 +1134,28 @@ folder_scan_header(struct _header_scan_state *s, int *lastone)
h->pool = mempool_new(8192, 4096);
#endif
/* FIXME: this info should be cached ? */
part = s->parts;
s->atleast = 5;
while (part) {
if (part->boundary)
s->atleast = MAX(s->atleast, part->boundarylen+2);
part = part->parent;
}
#if 0
s->atleast = MAX(s->atleast, 5);
if (s->parts)
s->atleast = MAX(s->atleast, s->parts->boundarylen+2);
#endif
if (part)
s->atleast = part->atleast;
else
s->atleast = 1;
*lastone = FALSE;
retry:
while ((len = folder_read(s))>0 && len >= s->atleast) { /* ensure we have at least enough room here */
inptr = s->inptr;
inend = s->inend-s->atleast;
while (inptr<=inend) {
/*printf(" '%.20s'\n", inptr);*/
start = inptr;
if (!s->midline) {
if ((part = folder_boundary_check(s, inptr, lastone))) {
if ((s->outptr>s->outbuf) || (inptr-start))
goto header_truncated; /* may not actually be truncated */
goto normal_exit;
}
@ -1164,15 +1170,15 @@ retry:
*start = ' ';
}
}
/* goto next line */
while ((*inptr++)!='\n')
;
g_assert(inptr<=s->inend+1);
header_append(s, start, inptr-1);
/* check against the real buffer end, not our 'atleast limited' end */
/* also make sure we have at least 1 char lookahead, so even if we found a \n at
the end, well, make out we didn't, and re-scan it next pass */
@ -1182,7 +1188,7 @@ retry:
} else {
s->midline = FALSE;
}
h(printf("midline = %s\n", s->midline?"TRUE":"FALSE"));
h(printf("outbuf[0] = %02x '%c' oubuf[1] = %02x '%c'\n",
s->outbuf[0], isprint(s->outbuf[0])?s->outbuf[0]:'.',
@ -1190,7 +1196,9 @@ retry:
h(printf("inptr[0] = %02x '%c' inptr[1] = %02x '%c'\n",
inptr[0], isprint(inptr[0])?inptr[0]:'.',
inptr[1], isprint(inptr[1])?inptr[1]:'.'));
/* this is wont handle no headers \n\n foobr - treats it as continuation */
/*
if (!s->midline
&& !(inptr[0] == ' ' || inptr[0] == '\t')) {
h(printf("ok, checking\n"));
@ -1200,23 +1208,34 @@ retry:
h(printf("header done?\n"));
goto header_done;
}
/* we always have at least _1_ char here ... */
if (s->outptr > s->outbuf && s->outptr[-1] == '\n')
s->outptr--;
s->outptr[0] = 0;
d(printf("header '%.10s' at %d\n", s->outbuf, s->header_start));
header_raw_append_parse(&h->headers, s->outbuf, s->header_start);
if (inptr[0]=='\n'
|| (inptr[0] == '\r' && inptr[1]=='\n')) {
inptr++;
*/
if (!s->midline) {
h(printf("ok, checking\n"));
if (s->outbuf == s->outptr
|| s->outbuf[0] == '\n'
|| (s->outbuf[0] == '\r' && s->outbuf[1]=='\n')) {
h(printf("header done?\n"));
goto header_done;
}
s->outptr = s->outbuf;
s->header_start = -1;
if (!(inptr[0] == ' ' || inptr[0] == '\t')) {
/* we always have at least _1_ char here ... */
if (s->outptr > s->outbuf && s->outptr[-1] == '\n')
s->outptr--;
s->outptr[0] = 0;
d(printf("header '%.10s' at %d\n", s->outbuf, s->header_start));
header_raw_append_parse(&h->headers, s->outbuf, s->header_start);
if (inptr[0]=='\n'
|| (inptr[0] == '\r' && inptr[1]=='\n')) {
inptr++;
goto header_done;
}
s->outptr = s->outbuf;
s->header_start = -1;
}
}
}
s->inptr = inptr;
@ -1227,43 +1246,43 @@ retry:
if (overpart) {
overpart = overpart->parent;
while (overpart) {
if (overpart->boundary && (overpart->boundarylen+2) < s->atleast) {
s->atleast = overpart->boundarylen+2;
if (overpart->boundary && (overpart->boundarylenfinal) < s->atleast) {
s->atleast = overpart->boundarylenfinal;
h(printf("Retrying next smaller part ...\n"));
goto retry;
}
overpart = overpart->parent;
}
}
if ((s->outptr > s->outbuf) || s->inend > s->inptr) {
start = s->inptr;
inptr = s->inend;
goto header_truncated;
}
s->atleast = atleast;
return h;
header_truncated:
header_append(s, start, inptr);
if (s->outptr>s->outbuf && s->outptr[-1] == '\n')
s->outptr--;
s->outptr[0] = 0;
if (s->outbuf[0] == '\n'
|| (s->outbuf[0] == '\r' && s->outbuf[1]=='\n')) {
goto header_done;
}
header_raw_append_parse(&h->headers, s->outbuf, s->header_start);
header_done:
part = s->parts;
s->outptr = s->outbuf;
normal_exit:
s->inptr = inptr;
@ -1281,28 +1300,16 @@ folder_scan_content(struct _header_scan_state *s, int *lastone, char **data, int
char *start;
int len;
struct _header_scan_stack *part, *overpart = s->parts;
int already_packed = FALSE;
int onboundary = FALSE;
c(printf("scanning content\n"));
/* FIXME: this info should be cached ? */
part = s->parts;
s->atleast = 5;
while (part) {
if (part->boundary) {
c(printf("boundary: %s\n", part->boundary));
s->atleast = MAX(s->atleast, part->boundarylen+2);
}
part = part->parent;
}
/* s->atleast = MAX(s->atleast, 5);*/
#if 0
if (s->parts)
s->atleast = MAX(s->atleast, s->parts->boundarylen+2);
#endif
if (part)
s->atleast = part->atleast;
else
s->atleast = 1;
*lastone = FALSE;
retry:
c(printf("atleast = %d\n", s->atleast));
@ -1316,65 +1323,43 @@ retry:
while (inptr<=inend) {
if (!s->midline
&& (part = folder_boundary_check(s, inptr, lastone))) {
if ( (inptr-start) ) {
onboundary = TRUE;
onboundary = TRUE;
/* since we truncate the boundary data, we need at least 1 char here spare,
to remain in the same state */
if ( (inptr-start) > 1)
goto content;
}
goto normal_exit;
}
/* otherwise, jump to the state of the boundary we actually found */
goto normal_exit; }
/* goto the next line */
while ((*inptr++)!='\n')
;
/* check against the real buffer end, not our 'atleast limited' end */
if (inptr> s->inend) {
inptr--;
/* check the sentinal, if we went past the atleast limit, and reset it to there */
if (inptr > inend+1) {
s->midline = TRUE;
inptr = inend+1;
} else {
s->midline = FALSE;
}
g_assert(inptr<=s->inend);
}
/* *sigh* so much for the beautiful simplicity of the code so far - here we
have the snot to deal with the nasty end-cases that come from the read-ahead
buffers we use */
/* what this does, is if we are somewhere near the end of the buffer,
force it to the front, and re-read, ensuring we bunch as much together
as possible, for the final read, without copying too much of the time */
/* make sure we dont loop forever, but also make sure we try smaller
boundaries, if there are any, so we dont miss any. */
/* this is not needed for the header scanner, since it copies its own
data */
c(printf("start offset = %d atleast = %d\n", start-s->inbuf, s->atleast));
if (start > (s->inbuf + s->atleast)) {
/* force a re-scan of this data */
s->inptr = start;
if (already_packed)
goto smaller_boundary;
c(printf("near the end, try and bunch things up a bit first\n"));
already_packed = TRUE;
} else {
c(printf("dumping what i've got ...\n"));
/* what would be nice here, is if that we're at eof, we bunch the last
little bit in the same content, but i dont think this is easy */
goto content_mid;
}
c(printf("ran out of input, dumping what i have (%d) bytes midline = %s\n",
inptr-start, s->midline?"TRUE":"FALSE"));
goto content;
}
c(printf("length read = %d\n", len));
smaller_boundary:
/* ok, we're at the end of the data, just make sure we're not missing out some small
truncated header markers */
if (overpart) {
overpart = overpart->parent;
while (overpart) {
if (overpart->boundary && (overpart->boundarylen+2) < s->atleast) {
s->atleast = overpart->boundarylen+2;
if (overpart->boundary && (overpart->boundarylenfinal) < s->atleast) {
s->atleast = overpart->boundarylenfinal;
c(printf("Retrying next smaller part ...\n"));
goto retry;
}
@ -1392,8 +1377,6 @@ smaller_boundary:
s->atleast = atleast;
return NULL;
content_mid:
s->midline = TRUE;
content:
part = s->parts;
normal_exit:
@ -1402,12 +1385,12 @@ normal_exit:
*data = start;
/* if we hit a boundary, we should not include the closing \n */
if (onboundary)
if (onboundary && (inptr-start)>0)
*length = inptr-start-1;
else
*length = inptr-start;
/* printf("got %scontent: %.*s", s->midline?"partial ":"", inptr-start, start);*/
/*printf("got %scontent: '%.*s'\n", s->midline?"partial ":"", inptr-start, start);*/
return part;
}
@ -1559,6 +1542,7 @@ tail_recurse:
h = g_malloc0(sizeof(*h));
h->boundary = g_strdup("From ");
h->boundarylen = strlen(h->boundary);
h->boundarylenfinal = h->boundarylen;
folder_push_part(s, h);
h = s->parts;
@ -1602,6 +1586,7 @@ tail_recurse:
if (bound) {
d(printf("multipart, boundary = %s\n", bound));
h->boundarylen = strlen(bound)+2;
h->boundarylenfinal = h->boundarylen+2;
h->boundary = g_malloc(h->boundarylen+3);
sprintf(h->boundary, "--%s--", bound);
type = HSCAN_MULTIPART;
@ -1668,8 +1653,8 @@ tail_recurse:
/* check for any filter completion data */
if (*datalength > 0) {
while (f) {
camel_mime_filter_filter(f->filter, *databuffer, *datalength, presize,
databuffer, datalength, &presize);
camel_mime_filter_complete(f->filter, *databuffer, *datalength, presize,
databuffer, datalength, &presize);
f = f->next;
}
}

View File

@ -22,7 +22,7 @@
#include "camel-stream-filter.h"
#define d(x)
#include <stdio.h>
/*#include <stdio.h>*/
struct _filter {
struct _filter *next;