Skip to content

Commit 124fa21

Browse files
committed
Improve the processing of rfc3676
rfc3676 formatted messages can have both fixed and flowed lines. delsp wasn't always being removed fix folding of lines with quotes
1 parent dffa3a2 commit 124fa21

File tree

3 files changed

+62
-34
lines changed

3 files changed

+62
-34
lines changed

src/hypermail.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ struct body {
236236
char attached; /* part of attachment */
237237
char demimed; /* if this is a header, this is set to TRUE if
238238
it has passed the decoderfc2047() function */
239+
int format_flowed; /* TRUE if this a text/plain f=f line */
239240
int msgnum;
240241
struct body *next;
241242
};
@@ -286,8 +287,8 @@ struct emailinfo {
286287
long datenum; /* moved here from 'struct header' */
287288
long flags; /* added 1999-03-19 for the new thread output functions */
288289

289-
#define PRINT_THREAD 1 /* set if already used in the thread output */
290-
#define USED_THREAD 2 /* set if already stored in threadlist */
290+
#define PRINT_THREAD 1 /* set if already used in the thread output */
291+
#define USED_THREAD 2 /* set if already stored in threadlist */
291292

292293
int initial_next_in_thread; /* msgnum written as next during normal print*/
293294

@@ -330,6 +331,10 @@ struct attach {
330331
#define BODY_HTMLIZED (1<<1) /* this is already htmlified */
331332
#define BODY_HEADER (1<<2) /* this is a header line */
332333
#define BODY_ATTACHED (1<<3) /* this line was attached */
334+
#define BODY_FORMAT_FLOWED (1<<4) /* this line is format-flowed */
335+
#define BODY_DEL_SSQ (1<<5) /* remove both space stuffing and
336+
* quotes where applicable for f=f */
337+
333338

334339
struct boundary {
335340
struct boundary *next;

src/parse.c

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,31 +1117,29 @@ static int get_quotelevel (const char *line)
11171117
** headers), the previous line quotelevel, and a flag saying if the
11181118
** previous line was marked as a continuing one.
11191119
**
1120-
** The function updates the quotelevel to
1121-
** that of the current parsed line. The function will update the
1122-
** continue_prev_flow_flag to say if the current line should be joined
1123-
** to the previous one, and, if positive, the padding offset that
1124-
** should be applied to the current line when merging it (for skipping
1125-
** quotes or space-stuffing).
1120+
** The function updates the quotelevel to that of the current parsed
1121+
** line. The function will update the continue_prev_flow_flag to say
1122+
** if the current line should be joined to the previous one, and, if
1123+
** positive, the padding offset that should be applied to the current
1124+
** line when merging it (for skipping quotes or space-stuffing).
11261125
**
1127-
** If delsp is true, the function will remove the space in the soft
1126+
** If delsp is true, the function will remove the space in the soft
11281127
** line break if the line is flowed.
11291128
**
11301129
** The function returns true if the current line is flowed.
11311130
**
11321131
*/
11331132
static bool rfc3676_handler (char *line, bool delsp_flag, int *quotelevel,
1134-
bool *continue_prev_flow_flag, int *padding)
1133+
bool *continue_prev_flow_flag)
11351134
{
11361135
int new_quotelevel = 0;
1137-
int space_stuffing = 0;
11381136
int tmp_padding = 0;
11391137
bool sig_sep = FALSE;
11401138
bool flowed = FALSE;
11411139

11421140
/* rules for evaluation if the flow should stop:
11431141
1. new quote level is different from previous one
1144-
2. The line ends with a signature "[(quotes)][(ss)]-- \n"
1142+
2. The line is a signature "[(quotes)][(ss)]-- \n"
11451143
3. The line is a hard break "\n"
11461144
4. The message body has ended
11471145
@@ -1162,6 +1160,7 @@ static bool rfc3676_handler (char *line, bool delsp_flag, int *quotelevel,
11621160
11631161
special case, space-stuffed or f=f? A line that has only this content:
11641162
" \n": this is a space-stuffed newline.
1163+
@@ test this special case with mutt
11651164
*/
11661165

11671166

@@ -1176,8 +1175,7 @@ static bool rfc3676_handler (char *line, bool delsp_flag, int *quotelevel,
11761175
if (rfc3676_ishardlb(line)) {
11771176
/* Hard crlf, reset flags */
11781177
*quotelevel = 0;
1179-
*padding = 0;
1180-
/* *continue_prev_flow_flag = FALSE; */
1178+
*continue_prev_flow_flag = FALSE;
11811179
#if DEBUG_PARSE
11821180
printf("RFC3676: hard CRLF detected. Stopping ff\n");
11831181
#endif
@@ -1207,7 +1205,6 @@ static bool rfc3676_handler (char *line, bool delsp_flag, int *quotelevel,
12071205
** skip space stuffing if any
12081206
*/
12091207
if (line[tmp_padding] == ' ') {
1210-
space_stuffing = 1;
12111208
tmp_padding++;
12121209
#if DEBUG_PARSE
12131210
printf("RFC3676: space-stuffing detected; skipping space\n");
@@ -1221,13 +1218,12 @@ static bool rfc3676_handler (char *line, bool delsp_flag, int *quotelevel,
12211218
/* Hard crlf, reset flags */
12221219
/* *continue_prev_flow_flag = FALSE; */
12231220
*quotelevel = new_quotelevel;
1224-
*padding = 0;
12251221
#if DEBUG_PARSE
12261222
printf("RFC3676: hard CRLF detected after quote. Stopping ff\n");
12271223
#endif
12281224
return FALSE;
12291225
}
1230-
1226+
12311227
/*
12321228
** signature detection
12331229
*/
@@ -1280,12 +1276,6 @@ static bool rfc3676_handler (char *line, bool delsp_flag, int *quotelevel,
12801276
*/
12811277
*quotelevel = new_quotelevel;
12821278

1283-
if (*continue_prev_flow_flag) {
1284-
*padding = new_quotelevel + space_stuffing;
1285-
} else {
1286-
*padding = (new_quotelevel == 0) ? space_stuffing : 0;
1287-
}
1288-
12891279
#if DEBUG_PARSE
12901280
if (*continue_prev_flow_flag)
12911281
printf("RFC3676: Continuing previous flow\n");
@@ -3063,23 +3053,27 @@ msgid);
30633053
}
30643054
}
30653055
else {
3066-
int padding; /* used for skipping padding detected by rfc3676_handler,
3067-
which seems smarter than moving all the bytes in data
3068-
before injecting it into addbody */
30693056
if (!isinheader && (textplain_format == FORMAT_FLOWED)) {
3057+
/* remove both space stuffing and quotes
3058+
* where applicable for f=f */
3059+
bodyflags |= BODY_DEL_SSQ;
30703060
flowed_line = rfc3676_handler (data, delsp_flag, &quotelevel,
3071-
&continue_previous_flow_flag,
3072-
&padding);
3061+
&continue_previous_flow_flag);
30733062
if (continue_previous_flow_flag) {
30743063
bodyflags |= BODY_CONTINUE;
30753064
} else {
30763065
bodyflags &= ~BODY_CONTINUE;
3066+
if (flowed_line) {
3067+
bodyflags |= BODY_FORMAT_FLOWED;
3068+
} else {
3069+
bodyflags &= ~BODY_FORMAT_FLOWED;
3070+
}
30773071
}
30783072
continue_previous_flow_flag = flowed_line;
30793073
} else {
3080-
padding = 0;
3074+
bodyflags &= ~BODY_DEL_SSQ;
30813075
}
3082-
bp = addbody(bp, &lp, data + padding,
3076+
bp = addbody(bp, &lp, data,
30833077
(content == CONTENT_HTML ?
30843078
BODY_HTMLIZED : 0) | bodyflags);
30853079
}

src/struct.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -912,14 +912,38 @@ struct body *addbody(struct body *bp, struct body **lp, /* points to the last po
912912
{
913913
struct body *tempnode;
914914
struct body *newnode = NULL;
915-
915+
char *unstuffed_line = line;
916+
int free_unstuffed_line = 0;
917+
918+
/* delete both space stuffing and quotes where applicable for f=f */
919+
if (flags & BODY_DEL_SSQ) {
920+
if (flags & BODY_CONTINUE) {
921+
/* delete all quote levels, we're reusing those of the precedent line */
922+
while (*unstuffed_line == '>') {
923+
unstuffed_line++;
924+
}
925+
}
926+
/* deleting space-stuffing at beginning of line */
927+
if (unstuffed_line[0] == ' ') {
928+
unstuffed_line++;
929+
}
930+
else if (unstuffed_line[0] == '>') {
931+
char *delsp_line = rfc3676_delsp_quotes(unstuffed_line);
932+
if (delsp_line) {
933+
unstuffed_line = delsp_line;
934+
free_unstuffed_line = 1;
935+
}
936+
}
937+
}
938+
916939
if (!(flags & BODY_CONTINUE)) {
917940
newnode = (struct body *)emalloc(sizeof(struct body));
918941
memset(newnode, 0, sizeof(struct body));
919-
newnode->line = spamify(strsav(line));
942+
newnode->line = spamify(strsav(unstuffed_line));
920943
newnode->html = (flags & BODY_HTMLIZED) ? 1 : 0;
921944
newnode->header = (flags & BODY_HEADER) ? 1 : 0;
922945
newnode->attached = (flags & BODY_ATTACHED) ? 1 : 0;
946+
newnode->format_flowed = (flags & BODY_FORMAT_FLOWED) ? 1 : 0;
923947
newnode->next = NULL;
924948
}
925949
if (bp == NULL) {
@@ -935,7 +959,7 @@ struct body *addbody(struct body *bp, struct body **lp, /* points to the last po
935959
char *newbuf;
936960

937961
/* get the new size + 1 for the terminating zero */
938-
newlen = strlen(tempnode->line) + strlen(line) + 1;
962+
newlen = strlen(tempnode->line) + strlen(unstuffed_line) + 1;
939963

940964
/* extend the former memory area: */
941965
newbuf = (char *)realloc(tempnode->line, newlen);
@@ -949,7 +973,7 @@ struct body *addbody(struct body *bp, struct body **lp, /* points to the last po
949973
*lf = 0;
950974

951975
/* append the new part */
952-
strcat(newbuf, line);
976+
strcat(newbuf, unstuffed_line);
953977

954978
/* point out the new buffer instead */
955979
tempnode->line = newbuf;
@@ -960,6 +984,11 @@ struct body *addbody(struct body *bp, struct body **lp, /* points to the last po
960984
*lp = newnode;
961985
}
962986
}
987+
988+
if (free_unstuffed_line) {
989+
free(unstuffed_line);
990+
}
991+
963992
return bp;
964993
}
965994

0 commit comments

Comments
 (0)