From ce862c88f8023d62309d0553fa7bfd3d4e885305 Mon Sep 17 00:00:00 2001 From: cketti Date: Wed, 7 Jan 2015 02:29:56 +0100 Subject: [PATCH] Change AttachmentProvider to use the new database structure --- .../com/fsck/k9/mailstore/LocalStore.java | 74 ++++++++++++++- .../fsck/k9/provider/AttachmentProvider.java | 92 +++++++++++-------- 2 files changed, 125 insertions(+), 41 deletions(-) diff --git a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalStore.java b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalStore.java index b12e0a936..a33b44bc0 100644 --- a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalStore.java +++ b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalStore.java @@ -31,8 +31,15 @@ import com.fsck.k9.search.LocalSearch; import com.fsck.k9.search.SearchSpecification.Attribute; import com.fsck.k9.search.SearchSpecification.Searchfield; import com.fsck.k9.search.SqlQueryBuilder; +import org.apache.james.mime4j.codec.Base64InputStream; +import org.apache.james.mime4j.codec.QuotedPrintableInputStream; +import org.apache.james.mime4j.util.MimeUtil; +import java.io.ByteArrayInputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; @@ -648,7 +655,7 @@ public class LocalStore extends Store implements Serializable { return null; } String name = cursor.getString(0); - int size = cursor.getInt(1); + long size = cursor.getLong(1); String mimeType = cursor.getString(2); final AttachmentInfo attachmentInfo = new AttachmentInfo(); @@ -664,9 +671,72 @@ public class LocalStore extends Store implements Serializable { }); } + public InputStream getAttachmentInputStream(final String attachmentId) throws MessagingException { + return database.execute(false, new DbCallback() { + @Override + public InputStream doDbWork(final SQLiteDatabase db) throws WrappedException { + Cursor cursor = db.query("message_parts", + new String[] { "data_location", "data", "encoding" }, + "id = ?", + new String[] { attachmentId }, + null, null, null); + try { + if (!cursor.moveToFirst()) { + return null; + } + + int location = cursor.getInt(0); + String encoding = cursor.getString(2); + + InputStream rawInputStream = getRawAttachmentInputStream(cursor, location, attachmentId); + return getDecodingInputStream(rawInputStream, encoding); + } finally { + cursor.close(); + } + } + }); + } + + private InputStream getRawAttachmentInputStream(Cursor cursor, int location, String attachmentId) { + switch (location) { + case DataLocation.IN_DATABASE: { + byte[] data = cursor.getBlob(1); + return new ByteArrayInputStream(data); + } + case DataLocation.ON_DISK: { + File file = getAttachmentFile(attachmentId); + try { + return new FileInputStream(file); + } catch (FileNotFoundException e) { + throw new WrappedException(e); + } + } + default: { + throw new IllegalStateException("No attachment data available"); + } + } + } + + private InputStream getDecodingInputStream(InputStream rawInputStream, String encoding) { + if (MimeUtil.ENC_BASE64.equals(encoding)) { + return new Base64InputStream(rawInputStream); + } + if (MimeUtil.ENC_QUOTED_PRINTABLE.equals(encoding)) { + return new QuotedPrintableInputStream(rawInputStream); + } + + return rawInputStream; + } + + private File getAttachmentFile(String attachmentId) { + final StorageManager storageManager = StorageManager.getInstance(context); + final File attachmentDirectory = storageManager.getAttachmentDirectory(uUid, database.getStorageProviderId()); + return new File(attachmentDirectory, attachmentId); + } + public static class AttachmentInfo { public String name; - public int size; //FIXME: use long + public long size; public String type; } diff --git a/k9mail/src/main/java/com/fsck/k9/provider/AttachmentProvider.java b/k9mail/src/main/java/com/fsck/k9/provider/AttachmentProvider.java index 75fdcef35..579861b6b 100644 --- a/k9mail/src/main/java/com/fsck/k9/provider/AttachmentProvider.java +++ b/k9mail/src/main/java/com/fsck/k9/provider/AttachmentProvider.java @@ -19,7 +19,7 @@ import com.fsck.k9.mail.MessagingException; import com.fsck.k9.mail.internet.MimeUtility; import com.fsck.k9.mailstore.LocalStore; import com.fsck.k9.mailstore.LocalStore.AttachmentInfo; -import com.fsck.k9.mailstore.StorageManager; +import org.openintents.openpgp.util.ParcelFileDescriptorUtil; import java.io.*; import java.util.List; @@ -156,8 +156,6 @@ public class AttachmentProvider extends ContentProvider { @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { - File file; - List segments = uri.getPathSegments(); String accountUuid = segments.get(0); String attachmentId = segments.get(1); @@ -167,36 +165,10 @@ public class AttachmentProvider extends ContentProvider { int width = Integer.parseInt(segments.get(3)); int height = Integer.parseInt(segments.get(4)); - file = getThumbnailFile(getContext(), accountUuid, attachmentId); - if (!file.exists()) { - String type = getType(accountUuid, attachmentId, FORMAT_VIEW, null); - try { - FileInputStream in = new FileInputStream(getFile(accountUuid, attachmentId)); - try { - Bitmap thumbnail = createThumbnail(type, in); - if (thumbnail != null) { - thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true); - FileOutputStream out = new FileOutputStream(file); - try { - thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out); - } finally { - out.close(); - } - } - } finally { - try { - in.close(); - } catch (Throwable ignore) { /* ignore */ } - } - } catch (IOException ioe) { - return null; - } - } - } else { - file = getFile(accountUuid, attachmentId); + return openThumbnail(accountUuid, attachmentId, width, height); } - return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); + return openAttachment(accountUuid, attachmentId); } @Override @@ -282,18 +254,60 @@ public class AttachmentProvider extends ContentProvider { return type; } - private File getFile(String accountUuid, String id) throws FileNotFoundException { - Account account = Preferences.getPreferences(getContext()).getAccount(accountUuid); + private ParcelFileDescriptor openThumbnail(String accountUuid, String attachmentId, int width, int height) + throws FileNotFoundException { - File attachmentsDir = StorageManager.getInstance(getContext()).getAttachmentDirectory(accountUuid, - account.getLocalStorageProviderId()); - - File file = new File(attachmentsDir, id); + File file = getThumbnailFile(getContext(), accountUuid, attachmentId); if (!file.exists()) { - throw new FileNotFoundException(file.getAbsolutePath()); + String type = getType(accountUuid, attachmentId, FORMAT_VIEW, null); + try { + InputStream in = getAttachmentInputStream(accountUuid, attachmentId); + try { + Bitmap thumbnail = createThumbnail(type, in); + if (thumbnail != null) { + thumbnail = Bitmap.createScaledBitmap(thumbnail, width, height, true); + FileOutputStream out = new FileOutputStream(file); + try { + thumbnail.compress(Bitmap.CompressFormat.PNG, 100, out); + } finally { + try { + out.close(); + } catch (IOException e) { + Log.e(K9.LOG_TAG, "Error saving thumbnail", e); + } + } + } + } finally { + try { + in.close(); + } catch (Throwable ignore) { /* ignore */ } + } + } catch (MessagingException e) { + Log.e(K9.LOG_TAG, "Error getting InputStream for attachment", e); + return null; + } } - return file; + return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); + } + + private ParcelFileDescriptor openAttachment(String accountUuid, String attachmentId) { + try { + InputStream inputStream = getAttachmentInputStream(accountUuid, attachmentId); + return ParcelFileDescriptorUtil.pipeFrom(inputStream, null); + } catch (MessagingException e) { + Log.e(K9.LOG_TAG, "Error getting InputStream for attachment", e); + return null; + } catch (IOException e) { + Log.e(K9.LOG_TAG, "Error creating ParcelFileDescriptor", e); + return null; + } + } + + private InputStream getAttachmentInputStream(String accountUuid, String attachmentId) throws MessagingException { + final Account account = Preferences.getPreferences(getContext()).getAccount(accountUuid); + LocalStore localStore = LocalStore.getInstance(account, getContext()); + return localStore.getAttachmentInputStream(attachmentId); } private Bitmap createThumbnail(String type, InputStream data) {