129 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			129 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| From: A <author@example.com>
 | |
| Subject: [PATCH] mailinfo: support format=flowed
 | |
| Message-ID: <aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa@example.com>
 | |
| Date: Sat, 25 Aug 2018 22:04:50 +0200
 | |
| User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101
 | |
|  Thunderbird/60.0
 | |
| MIME-Version: 1.0
 | |
| Content-Type: text/plain; charset=utf-8; format=flowed
 | |
| Content-Language: en-US
 | |
| Content-Transfer-Encoding: 7bit
 | |
| 
 | |
| ---
 | |
|   mailinfo.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 | |
|   1 file changed, 62 insertions(+), 2 deletions(-)
 | |
| 
 | |
| diff --git a/mailinfo.c b/mailinfo.c
 | |
| index 3281a37d51..b395adbdf2 100644
 | |
| --- a/mailinfo.c
 | |
| +++ b/mailinfo.c
 | |
| @@ -237,11 +237,22 @@ static int slurp_attr(const char *line, const char 
 | |
| *name, struct strbuf *attr)
 | |
|   	return 1;
 | |
|   }
 | |
| 
 | |
| +static int has_attr_value(const char *line, const char *name, const 
 | |
| char *value)
 | |
| +{
 | |
| +	struct strbuf sb = STRBUF_INIT;
 | |
| +	int rc = slurp_attr(line, name, &sb) && !strcasecmp(sb.buf, value);
 | |
| +	strbuf_release(&sb);
 | |
| +	return rc;
 | |
| +}
 | |
| +
 | |
|   static void handle_content_type(struct mailinfo *mi, struct strbuf *line)
 | |
|   {
 | |
|   	struct strbuf *boundary = xmalloc(sizeof(struct strbuf));
 | |
|   	strbuf_init(boundary, line->len);
 | |
| 
 | |
| +	mi->format_flowed = has_attr_value(line->buf, "format=", "flowed");
 | |
| +	mi->delsp = has_attr_value(line->buf, "delsp=", "yes");
 | |
| +
 | |
|   	if (slurp_attr(line->buf, "boundary=", boundary)) {
 | |
|   		strbuf_insert(boundary, 0, "--", 2);
 | |
|   		if (++mi->content_top >= &mi->content[MAX_BOUNDARIES]) {
 | |
| @@ -964,6 +975,52 @@ static int handle_boundary(struct mailinfo *mi, 
 | |
| struct strbuf *line)
 | |
|   	return 1;
 | |
|   }
 | |
| 
 | |
| +static void handle_filter_flowed(struct mailinfo *mi, struct strbuf *line,
 | |
| +				 struct strbuf *prev)
 | |
| +{
 | |
| +	size_t len = line->len;
 | |
| +	const char *rest;
 | |
| +
 | |
| +	if (!mi->format_flowed) {
 | |
| +		handle_filter(mi, line);
 | |
| +		return;
 | |
| +	}
 | |
| +
 | |
| +	if (line->buf[len - 1] == '\n') {
 | |
| +		len--;
 | |
| +		if (len && line->buf[len - 1] == '\r')
 | |
| +			len--;
 | |
| +	}
 | |
| +
 | |
| +	/* Keep signature separator as-is. */
 | |
| +	if (skip_prefix(line->buf, "-- ", &rest) && rest - line->buf == len) {
 | |
| +		if (prev->len) {
 | |
| +			handle_filter(mi, prev);
 | |
| +			strbuf_reset(prev);
 | |
| +		}
 | |
| +		handle_filter(mi, line);
 | |
| +		return;
 | |
| +	}
 | |
| +
 | |
| +	/* Unstuff space-stuffed line. */
 | |
| +	if (len && line->buf[0] == ' ') {
 | |
| +		strbuf_remove(line, 0, 1);
 | |
| +		len--;
 | |
| +	}
 | |
| +
 | |
| +	/* Save flowed line for later, but without the soft line break. */
 | |
| +	if (len && line->buf[len - 1] == ' ') {
 | |
| +		strbuf_add(prev, line->buf, len - !!mi->delsp);
 | |
| +		return;
 | |
| +	}
 | |
| +
 | |
| +	/* Prepend any previous partial lines */
 | |
| +	strbuf_insert(line, 0, prev->buf, prev->len);
 | |
| +	strbuf_reset(prev);
 | |
| +
 | |
| +	handle_filter(mi, line);
 | |
| +}
 | |
| +
 | |
|   static void handle_body(struct mailinfo *mi, struct strbuf *line)
 | |
|   {
 | |
|   	struct strbuf prev = STRBUF_INIT;
 | |
| @@ -1012,7 +1069,7 @@ static void handle_body(struct mailinfo *mi, 
 | |
| struct strbuf *line)
 | |
|   						strbuf_addbuf(&prev, sb);
 | |
|   						break;
 | |
|   					}
 | |
| -				handle_filter(mi, sb);
 | |
| +				handle_filter_flowed(mi, sb, &prev);
 | |
|   			}
 | |
|   			/*
 | |
|   			 * The partial chunk is saved in "prev" and will be
 | |
| @@ -1022,13 +1079,16 @@ static void handle_body(struct mailinfo *mi, 
 | |
| struct strbuf *line)
 | |
|   			break;
 | |
|   		}
 | |
|   		default:
 | |
| -			handle_filter(mi, line);
 | |
| +			handle_filter_flowed(mi, line, &prev);
 | |
|   		}
 | |
| 
 | |
|   		if (mi->input_error)
 | |
|   			break;
 | |
|   	} while (!strbuf_getwholeline(line, mi->input, '\n'));
 | |
| 
 | |
| +	if (prev.len)
 | |
| +		handle_filter(mi, &prev);
 | |
| +
 | |
|   	flush_inbody_header_accum(mi);
 | |
| 
 | |
|   handle_body_out:
 | |
| -- 
 | |
| 2.18.0
 |