dovecot-2.2-pigeonhole: lib-sieve: util: edit-mail: Added header...

pigeonhole at rename-it.nl pigeonhole at rename-it.nl
Wed Jul 30 23:37:30 UTC 2014


details:   http://hg.rename-it.nl/dovecot-2.2-pigeonhole/rev/b68ddffa0ac1
changeset: 1903:b68ddffa0ac1
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Thu Jul 31 01:37:22 2014 +0200
description:
lib-sieve: util: edit-mail: Added header replacement API.

diffstat:

 src/lib-sieve/util/edit-mail.c |  336 +++++++++++++++++++++++++++++++---------
 src/lib-sieve/util/edit-mail.h |    7 +
 2 files changed, 269 insertions(+), 74 deletions(-)

diffs (truncated from 429 to 300 lines):

diff -r 6962669ad2e6 -r b68ddffa0ac1 src/lib-sieve/util/edit-mail.c
--- a/src/lib-sieve/util/edit-mail.c	Wed Jul 30 19:57:17 2014 +0200
+++ b/src/lib-sieve/util/edit-mail.c	Thu Jul 31 01:37:22 2014 +0200
@@ -430,6 +430,45 @@
 
 /* Header modification */
 
+static inline char *_header_value_unfold
+(const char *value)
+{
+	string_t *out;
+	unsigned int i;
+
+	for ( i = 0; value[i] != '\0'; i++ ) {
+		if (value[i] == '\r' || value[i] == '\n')
+			break;
+	}
+	if ( value[i] == '\0' ) {
+		return i_strdup(value);
+	}
+
+	out = t_str_new(i + strlen(value+i) + 10);
+	str_append_n(out, value, i);
+	for ( ; value[i] != '\0'; i++ ) {
+		if (value[i] == '\n') {
+			i++;
+			if (value[i] == '\0')
+				break;
+
+			switch ( value[i] ) {
+			case ' ': 
+				str_append_c(out, ' ');
+				break;
+			case '\t':
+			default:
+				str_append_c(out, '\t');
+			}
+		} else {
+			if (value[i] != '\r')
+				str_append_c(out, value[i]);
+		}
+	}
+
+	return i_strndup(str_c(out), str_len(out));
+}
+
 static struct _header_index *edit_mail_header_find
 (struct edit_mail *edmail, const char *field_name)
 {
@@ -482,6 +521,50 @@
 	return header_idx;
 }
 
+static struct _header_field_index *
+edit_mail_header_field_create
+(struct edit_mail *edmail, const char *field_name, const char *value)
+{
+	struct _header_index *header_idx;
+	struct _header *header;
+	struct _header_field_index *field_idx;
+	struct _header_field *field;
+	unsigned int lines;
+
+	/* Get/create header index item */
+	header_idx = edit_mail_header_create(edmail, field_name);
+	header = header_idx->header;
+
+	/* Create new field index item */
+	field_idx = i_new(struct _header_field_index, 1);
+	field_idx->header = header_idx;
+	field_idx->field = field = _header_field_create(header);
+
+	/* Create header field data (folded if necessary) */
+	T_BEGIN {
+		string_t *enc_value, *data;
+
+		enc_value = t_str_new(strlen(field_name) + strlen(value) + 64);
+		data = t_str_new(strlen(field_name) + strlen(value) + 128);
+
+		message_header_encode(value, enc_value);
+
+		lines = rfc2822_header_append
+			(data, field_name, str_c(enc_value), edmail->crlf, &field->body_offset);
+
+		/* Copy to new field */
+		field->data = i_strndup(str_data(data), str_len(data));
+		field->size = str_len(data);
+		field->virtual_size = ( edmail->crlf ? field->size : field->size + lines );
+		field->lines = lines;
+	} T_END;
+
+	/* Record original (utf8) value */
+	field->utf8_value = _header_value_unfold(value);
+
+	return field_idx;
+}
+
 static void edit_mail_header_field_delete
 (struct edit_mail *edmail, struct _header_field_index *field_idx,
 	bool update_index)
@@ -528,6 +611,86 @@
 	i_free(field_idx);
 }
 
+static void edit_mail_header_field_replace
+(struct edit_mail *edmail, struct _header_field_index *field_idx,
+	const char *newname, const char *newvalue, bool update_index)
+{
+	struct _header_field_index *field_idx_new;
+	struct _header_index *header_idx = field_idx->header, *header_idx_new;
+	struct _header_field *field = field_idx->field, *field_new;
+
+	i_assert( header_idx != NULL );
+	i_assert( newname != NULL || newvalue != NULL );
+
+	if ( newname == NULL )
+		newname = header_idx->header->name;
+	if ( newvalue == NULL )
+		newvalue = field_idx->field->utf8_value;
+	field_idx_new = edit_mail_header_field_create
+		(edmail, newname, newvalue);
+	field_new = field_idx_new->field;
+	header_idx_new = field_idx_new->header;
+
+	edmail->hdr_size.physical_size -= field->size;
+	edmail->hdr_size.virtual_size -= field->virtual_size;
+	edmail->hdr_size.lines -= field->lines;
+
+	edmail->hdr_size.physical_size += field_new->size;
+	edmail->hdr_size.virtual_size += field_new->virtual_size;
+	edmail->hdr_size.lines += field_new->lines;
+
+	/* Replace header field index */
+	field_idx_new->prev = field_idx->prev;
+	field_idx_new->next = field_idx->next;
+	if ( field_idx->prev != NULL )
+		field_idx->prev->next = field_idx_new;
+	if ( field_idx->next != NULL )
+		field_idx->next->prev = field_idx_new;
+	if (edmail->header_fields_head == field_idx)
+		edmail->header_fields_head = field_idx_new;
+	if (edmail->header_fields_tail == field_idx)
+		edmail->header_fields_tail = field_idx_new;
+
+	if ( header_idx_new == header_idx ) {
+		if (header_idx->first == field_idx)
+			header_idx->first = field_idx_new;
+		if (header_idx->last == field_idx)
+			header_idx->last = field_idx_new;
+	} else {
+		header_idx->count--;
+		header_idx_new->count++;
+
+		if ( update_index ) {
+			if ( header_idx->count == 0 ) {
+				DLLIST2_REMOVE(&edmail->headers_head, &edmail->headers_tail, header_idx);
+				_header_unref(header_idx->header);
+				i_free(header_idx);
+			} else if ( header_idx->first == field_idx ) {
+				struct _header_field_index *hfield = header_idx->first->next;
+
+				while ( hfield != NULL && hfield->header != header_idx ) {
+					hfield = hfield->next;
+				}
+
+				i_assert( hfield != NULL );
+				header_idx->first = hfield;
+			} else if ( header_idx->last == field_idx ) {
+				struct _header_field_index *hfield = header_idx->last->prev;
+
+				while ( hfield != NULL && hfield->header != header_idx ) {
+					hfield = hfield->prev;
+				}
+
+				i_assert( hfield != NULL );
+				header_idx->last = hfield;
+			}
+		}
+	}
+
+	_header_field_unref(field_idx->field);
+	i_free(field_idx);
+}
+
 static inline char *_header_decode
 (const unsigned char *hdr_data, size_t hdr_data_len)
 {
@@ -704,86 +867,19 @@
 	return 1;
 }
 
-static inline char *_header_value_unfold
-(const char *value)
-{
-	string_t *out;
-	unsigned int i;
-
-	for ( i = 0; value[i] != '\0'; i++ ) {
-		if (value[i] == '\r' || value[i] == '\n')
-			break;
-	}
-	if ( value[i] == '\0' ) {
-		return i_strdup(value);
-	}
-
-	out = t_str_new(i + strlen(value+i) + 10);
-	str_append_n(out, value, i);
-	for ( ; value[i] != '\0'; i++ ) {
-		if (value[i] == '\n') {
-			i++;
-			if (value[i] == '\0')
-				break;
-
-			switch ( value[i] ) {
-			case ' ': 
-				str_append_c(out, ' ');
-				break;
-			case '\t':
-			default:
-				str_append_c(out, '\t');
-			}
-		} else {
-			if (value[i] != '\r')
-				str_append_c(out, value[i]);
-		}
-	}
-
-	return i_strndup(str_c(out), str_len(out));
-}
-
 void edit_mail_header_add
-(struct edit_mail *edmail, const char *field_name, const char *value, bool last)
+(struct edit_mail *edmail, const char *field_name, const char *value,
+	bool last)
 {
 	struct _header_index *header_idx;
-	struct _header *header;
 	struct _header_field_index *field_idx;
 	struct _header_field *field;
-	unsigned int lines;
 
 	edit_mail_modify(edmail);
 
-	/* Get/create header index item */
-	header_idx = edit_mail_header_create(edmail, field_name);
-	header = header_idx->header;
-
-	/* Create new field index item */
-	field_idx = i_new(struct _header_field_index, 1);
-	field_idx->header = header_idx;
-	field_idx->field = field = _header_field_create(header);
-
-	/* Create header field data (folded if necessary) */
-	T_BEGIN {
-		string_t *enc_value, *data;
-
-		enc_value = t_str_new(strlen(field_name) + strlen(value) + 64);
-		data = t_str_new(strlen(field_name) + strlen(value) + 128);
-
-		message_header_encode(value, enc_value);
-
-		lines = rfc2822_header_append
-			(data, field_name, str_c(enc_value), edmail->crlf, &field->body_offset);
-
-		/* Copy to new field */
-		field->data = i_strndup(str_data(data), str_len(data));
-		field->size = str_len(data);
-		field->virtual_size = ( edmail->crlf ? field->size : field->size + lines );
-		field->lines = lines;
-	} T_END;
-
-	/* Record original (utf8) value */
-	field->utf8_value = _header_value_unfold(value);
+	field_idx = edit_mail_header_field_create(edmail, field_name, value);
+	header_idx = field_idx->header;
+	field = field_idx->field;
 
 	/* Add it to the header field index */
 	if ( last ) {
@@ -802,7 +898,7 @@
 
 			edmail->appended_hdr_size.physical_size += field->size;
 			edmail->appended_hdr_size.virtual_size += field->virtual_size;
-			edmail->appended_hdr_size.lines += lines;
+			edmail->appended_hdr_size.lines += field->lines;
 		}
 	} else {
 		DLLIST2_PREPEND
@@ -817,7 +913,7 @@
 
 	edmail->hdr_size.physical_size += field->size;
 	edmail->hdr_size.virtual_size += field->virtual_size;
-	edmail->hdr_size.lines += lines;
+	edmail->hdr_size.lines += field->lines;
 }
 
 int edit_mail_header_delete
@@ -892,6 +988,80 @@
 	return ret;
 }


More information about the dovecot-cvs mailing list