Fix downloading/saving single message parts

This commit is contained in:
cketti 2015-01-10 04:04:37 +01:00
parent 743e640d8c
commit bd97004ebd
6 changed files with 83 additions and 40 deletions

View File

@ -2,14 +2,25 @@ package com.fsck.k9.mail;
public abstract class BodyPart implements Part {
private Multipart mParent;
private String serverExtra;
private Multipart parent;
@Override
public String getServerExtra() {
return serverExtra;
}
@Override
public void setServerExtra(String serverExtra) {
this.serverExtra = serverExtra;
}
public Multipart getParent() {
return mParent;
return parent;
}
public void setParent(Multipart parent) {
mParent = parent;
this.parent = parent;
}
public abstract void setEncoding(String encoding) throws MessagingException;

View File

@ -46,4 +46,8 @@ public interface Part {
*/
//TODO perhaps it would be clearer to use a flag "force7bit" in writeTo
void setUsing7bitTransport() throws MessagingException;
String getServerExtra();
void setServerExtra(String serverExtra);
}

View File

@ -11,28 +11,11 @@ import java.util.*;
public class MimeHeader {
private static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
* Application specific header that contains Store specific information about an attachment.
* In IMAP this contains the IMAP BODYSTRUCTURE part id so that the ImapStore can later
* retrieve the attachment at will from the server.
* The info is recorded from this header on LocalStore.appendMessages and is put back
* into the MIME data by LocalStore.fetch.
*/
public static final String HEADER_ANDROID_ATTACHMENT_STORE_DATA = "X-Android-Attachment-StoreData";
public static final String HEADER_CONTENT_TYPE = "Content-Type";
public static final String HEADER_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
public static final String HEADER_CONTENT_ID = "Content-ID";
/**
* Fields that should be omitted when writing the header using writeTo()
*/
private static final String[] writeOmitFields = {
// HEADER_ANDROID_ATTACHMENT_DOWNLOADED,
// HEADER_ANDROID_ATTACHMENT_ID,
HEADER_ANDROID_ATTACHMENT_STORE_DATA
};
private List<Field> mFields = new ArrayList<Field>();
private String mCharset = null;
@ -101,14 +84,12 @@ public class MimeHeader {
public void writeTo(OutputStream out) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out), 1024);
for (Field field : mFields) {
if (!Arrays.asList(writeOmitFields).contains(field.name)) {
if (field.hasRawData()) {
writer.write(field.getRaw());
} else {
writeNameValueField(writer, field);
}
writer.write("\r\n");
if (field.hasRawData()) {
writer.write(field.getRaw());
} else {
writeNameValueField(writer, field);
}
writer.write("\r\n");
}
writer.flush();
}

View File

@ -57,6 +57,7 @@ public class MimeMessage extends Message {
private Body mBody;
protected int mSize;
private String serverExtra;
public MimeMessage() {
}
@ -693,4 +694,16 @@ public class MimeMessage extends Message {
setEncoding(MimeUtil.ENC_QUOTED_PRINTABLE);
}
}
@Override
public String getServerExtra() {
return serverExtra;
}
@Override
public void setServerExtra(String serverExtra) {
this.serverExtra = serverExtra;
}
}

View File

@ -1455,13 +1455,9 @@ public class ImapStore extends RemoteStore {
throws MessagingException {
checkOpen(); //only need READ access
String[] parts = part.getHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA);
if (parts == null) {
return;
}
String partId = part.getServerExtra();
String fetch;
String partId = parts[0];
if ("TEXT".equalsIgnoreCase(partId)) {
fetch = String.format(Locale.US, "BODY.PEEK[TEXT]<0.%d>",
mStoreConfig.getMaximumAutoDownloadMessageSize());
@ -1834,7 +1830,7 @@ public class ImapStore extends RemoteStore {
if (part instanceof ImapMessage) {
((ImapMessage) part).setSize(size);
}
part.setHeader(MimeHeader.HEADER_ANDROID_ATTACHMENT_STORE_DATA, id);
part.setServerExtra(id);
}
}

View File

@ -672,6 +672,7 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
long parentId = cursor.getLong(2);
String mimeType = cursor.getString(3);
byte[] header = cursor.getBlob(6);
String serverExtra = cursor.getString(15);
final Part part;
if (id == message.getMessagePartId()) {
@ -698,6 +699,7 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
parseHeaderBytes(part, header);
}
partById.put(id, part);
part.setServerExtra(serverExtra);
boolean isMultipart = mimeType.startsWith("multipart/");
if (isMultipart) {
@ -1322,14 +1324,22 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
Part part = partContainer.part;
byte[] headerBytes = getHeaderBytes(part);
ContentValues cv = new ContentValues();
if (rootMessagePartId != -1) {
cv.put("root", rootMessagePartId);
}
cv.put("parent", partContainer.parent);
cv.put("seq", order);
cv.put("server_extra", part.getServerExtra());
partToContentValues(cv, part);
return db.insertOrThrow("message_parts", null, cv);
}
private void partToContentValues(ContentValues cv, Part part) throws IOException, MessagingException {
byte[] headerBytes = getHeaderBytes(part);
cv.put("mime_type", part.getMimeType());
cv.put("header", headerBytes);
cv.put("type", MessagePartType.UNKNOWN);
@ -1355,8 +1365,6 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
cv.put("data", bodyData);
cv.put("content_id", part.getContentId());
}
return db.insertOrThrow("message_parts", null, cv);
}
private byte[] getHeaderBytes(Part part) throws IOException, MessagingException {
@ -1403,9 +1411,39 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
public void addPartToMessage(final LocalMessage message, final Part part) throws MessagingException {
open(OPEN_MODE_RW);
throw new RuntimeException("Not implemented yet");
// localStore.notifyChange();
localStore.database.execute(false, new DbCallback<Void>() {
@Override
public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
String messagePartId;
Cursor cursor = db.query("message_parts", new String[] { "id" }, "root = ? AND server_extra = ?",
new String[] { Long.toString(message.getMessagePartId()), part.getServerExtra() },
null, null, null);
try {
if (!cursor.moveToFirst()) {
throw new IllegalStateException("Message part not found");
}
messagePartId = cursor.getString(0);
} finally {
cursor.close();
}
try {
ContentValues cv = new ContentValues();
partToContentValues(cv, part);
db.update("message_parts", cv, "id = ?", new String[] { messagePartId });
} catch (Exception e) {
Log.e(K9.LOG_TAG, "Error writing message part", e);
}
return null;
}
});
localStore.notifyChange();
}
/**
@ -1422,7 +1460,7 @@ public class LocalFolder extends Folder<LocalMessage> implements Serializable {
@Override
public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
db.update("messages", cv, "id = ?", new String[]
{ Long.toString(message.getId()) });
{ Long.toString(message.getId()) });
return null;
}
});