Resolves issue with non-UTF8 body and preview encoding. Closes #4408

This commit is contained in:
Eric Gregory 2011-11-22 15:18:30 -08:00
parent 43b0f0a16e
commit ce510e14a9
5 changed files with 88 additions and 7 deletions

View file

@ -116,7 +116,7 @@ public class Geary.Email : Object {
public Geary.EmailProperties? properties { get; private set; default = null; }
// PREVIEW
public RFC822.Text? preview { get; private set; default = null; }
public RFC822.PreviewText? preview { get; private set; default = null; }
public Geary.Email.Field fields { get; private set; default = Field.NONE; }
@ -198,7 +198,7 @@ public class Geary.Email : Object {
fields |= Field.PROPERTIES;
}
public void set_message_preview(Geary.RFC822.Text preview) {
public void set_message_preview(Geary.RFC822.PreviewText preview) {
this.preview = preview;
fields |= Field.PREVIEW;

View file

@ -90,7 +90,9 @@ public class Geary.Imap.Mailbox : Geary.SmartReference {
int plain_id = batch.add(new MailboxOperation(context, fetch_cmd));
int preview_id = NonblockingBatch.INVALID_ID;
int preview_charset_id = NonblockingBatch.INVALID_ID;
if (fields.require(Geary.Email.Field.PREVIEW)) {
// Preview text.
FetchBodyDataType fetch_preview = new FetchBodyDataType.peek(FetchBodyDataType.SectionPart.NONE,
{ 1 }, 0, Geary.Email.MAX_PREVIEW_BYTES, null);
Gee.List<FetchBodyDataType> list = new Gee.ArrayList<FetchBodyDataType>();
@ -99,6 +101,17 @@ public class Geary.Imap.Mailbox : Geary.SmartReference {
FetchCommand preview_cmd = new FetchCommand(msg_set, null, list);
preview_id = batch.add(new MailboxOperation(context, preview_cmd));
// Preview character set.
FetchBodyDataType fetch_preview_charset = new FetchBodyDataType.peek(
FetchBodyDataType.SectionPart.MIME,
{ 1 }, -1, -1, null);
Gee.List<FetchBodyDataType> list_charset = new Gee.ArrayList<FetchBodyDataType>();
list_charset.add(fetch_preview_charset);
FetchCommand preview_charset_cmd = new FetchCommand(msg_set, null, list_charset);
preview_charset_id = batch.add(new MailboxOperation(context, preview_charset_cmd));
}
yield batch.execute_all_async(cancellable);
@ -129,20 +142,38 @@ public class Geary.Imap.Mailbox : Geary.SmartReference {
// process preview FETCH results
if (preview_id != NonblockingBatch.INVALID_ID) {
if (preview_id != NonblockingBatch.INVALID_ID &&
preview_charset_id != NonblockingBatch.INVALID_ID) {
MailboxOperation preview_op = (MailboxOperation) batch.get_operation(preview_id);
CommandResponse preview_resp = (CommandResponse) batch.get_result(preview_id);
MailboxOperation preview_charset_op = (MailboxOperation)
batch.get_operation(preview_charset_id);
CommandResponse preview_charset_resp = (CommandResponse)
batch.get_result(preview_charset_id);
if (preview_resp.status_response.status != Status.OK) {
throw new ImapError.SERVER_ERROR("Server error for %s: %s", preview_op.cmd.to_string(),
preview_resp.to_string());
}
if (preview_charset_resp.status_response.status != Status.OK) {
throw new ImapError.SERVER_ERROR("Server error for %s: %s",
preview_charset_op.cmd.to_string(), preview_charset_resp.to_string());
}
FetchResults[] preview_results = FetchResults.decode(preview_resp);
FetchResults[] preview_header_results = FetchResults.decode(preview_charset_resp);
int i = 0;
foreach (FetchResults preview_res in preview_results) {
Geary.Email? preview_email = map.get(preview_res.msg_num);
if (preview_email != null)
preview_email.set_message_preview(new RFC822.Text(preview_res.get_body_data()[0]));
if (preview_email == null)
continue;
preview_email.set_message_preview(new RFC822.PreviewText(
preview_res.get_body_data()[0], preview_header_results[i].get_body_data()[0]));
i++;
}
}

View file

@ -149,3 +149,48 @@ public class Geary.RFC822.Full : Geary.Common.BlockMessageData, Geary.RFC822.Mes
}
}
// Used for decoding preview text.
public class Geary.RFC822.PreviewText : Geary.RFC822.Text {
public PreviewText(Geary.Memory.AbstractBuffer _buffer, Geary.Memory.AbstractBuffer?
preview_header = null) {
Geary.Memory.AbstractBuffer buffer = _buffer;
if (preview_header != null) {
string? charset = null;
string? encoding = null;
// Parse the header.
GMime.Stream header_stream = new GMime.StreamMem.with_buffer(
preview_header.get_array());
GMime.Parser parser = new GMime.Parser.with_stream(header_stream);
GMime.Part? part = parser.construct_part() as GMime.Part;
if (part != null) {
charset = part.get_content_type_parameter("charset");
encoding = part.get_header("Content-Transfer-Encoding");
}
GMime.StreamMem input_stream = new GMime.StreamMem.with_buffer(buffer.get_array());
ByteArray output = new ByteArray();
GMime.StreamMem output_stream = new GMime.StreamMem.with_byte_array(output);
output_stream.set_owner(false);
// Convert the encoding and character set.
GMime.StreamFilter filter = new GMime.StreamFilter(output_stream);
if (encoding != null)
filter.add(new GMime.FilterBasic(GMime.content_encoding_from_string(encoding), false));
if (charset != null)
filter.add(new GMime.FilterCharset(charset, "UTF8"));
input_stream.write_to_stream(filter);
uint8[] data = output.data;
data += (uint8) '\0';
buffer = new Geary.Memory.StringBuffer((string) data);
}
base (buffer);
}
}

View file

@ -183,7 +183,12 @@ public class Geary.RFC822.Message : Object {
GMime.StreamMem stream = new GMime.StreamMem.with_byte_array(byte_array);
stream.set_owner(false);
wrapper.write_to_stream(stream);
// Convert encoding to UTF-8.
GMime.StreamFilter stream_filter = new GMime.StreamFilter(stream);
stream_filter.add(new GMime.FilterCharset(part.get_content_type_parameter("charset"),
"UTF8"));
wrapper.write_to_stream(stream_filter);
return new Geary.Memory.Buffer(byte_array.data, byte_array.len);
}

View file

@ -120,7 +120,7 @@ public class Geary.Sqlite.MessageRow : Geary.Sqlite.Row {
email.set_message_body(new RFC822.Text(new Geary.Memory.StringBuffer(body)));
if (((fields & Geary.Email.Field.PREVIEW) != 0) && (preview != null))
email.set_message_preview(new RFC822.Text(new Geary.Memory.StringBuffer(preview)));
email.set_message_preview(new RFC822.PreviewText(new Geary.Memory.StringBuffer(preview)));
return email;
}