From bd700127dec2c9bef12cd0ac9fd8864a1e471cc9 Mon Sep 17 00:00:00 2001
From: ashley willis
Date: Mon, 23 Jan 2012 19:51:30 -0600
Subject: [PATCH 01/15] added montclair.edu to res/xml/providers.xml based on
http://oit.montclair.edu/documentation/msu_apps/email/AndroidPhoneSettingUpYourMSUEmailAccount.pdf
---
res/xml/providers.xml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/res/xml/providers.xml b/res/xml/providers.xml
index 9a7ecc794..62a7f9c75 100644
--- a/res/xml/providers.xml
+++ b/res/xml/providers.xml
@@ -170,6 +170,10 @@
+
+
+
+
From 7a3cadbf1c838f097332e5d04a05aeaabb6afa28 Mon Sep 17 00:00:00 2001
From: cketti
Date: Tue, 24 Jan 2012 14:34:32 +0100
Subject: [PATCH 02/15] Refactored AttachmentProvider.openFile()
---
.../fsck/k9/provider/AttachmentProvider.java | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/src/com/fsck/k9/provider/AttachmentProvider.java b/src/com/fsck/k9/provider/AttachmentProvider.java
index 542beab00..1a493a446 100644
--- a/src/com/fsck/k9/provider/AttachmentProvider.java
+++ b/src/com/fsck/k9/provider/AttachmentProvider.java
@@ -157,24 +157,24 @@ public class AttachmentProvider extends ContentProvider {
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ File file;
+
List segments = uri.getPathSegments();
- String dbName = segments.get(0); // "/sdcard/..." is URL-encoded and makes up only 1 segment
- String id = segments.get(1);
+ String accountUuid = segments.get(0);
+ String attachmentId = segments.get(1);
String format = segments.get(2);
+
if (FORMAT_THUMBNAIL.equals(format)) {
int width = Integer.parseInt(segments.get(3));
int height = Integer.parseInt(segments.get(4));
- String filename = "thmb_" + dbName + "_" + id + ".tmp";
- int index = dbName.lastIndexOf('/');
- if (index >= 0) {
- filename = /*dbName.substring(0, index + 1) + */"thmb_" + dbName.substring(index + 1) + "_" + id + ".tmp";
- }
+
+ String filename = "thmb_" + accountUuid + "_" + attachmentId + ".tmp";
File dir = getContext().getCacheDir();
- File file = new File(dir, filename);
+ file = new File(dir, filename);
if (!file.exists()) {
- String type = getType(dbName, id, FORMAT_VIEW);
+ String type = getType(accountUuid, attachmentId, FORMAT_VIEW);
try {
- FileInputStream in = new FileInputStream(getFile(dbName, id));
+ FileInputStream in = new FileInputStream(getFile(accountUuid, attachmentId));
try {
Bitmap thumbnail = createThumbnail(type, in);
if (thumbnail != null) {
@@ -187,18 +187,17 @@ public class AttachmentProvider extends ContentProvider {
}
}
} finally {
- try { in.close(); } catch (Throwable ignore) {}
+ try { in.close(); } catch (Throwable ignore) { /* ignore */ }
}
} catch (IOException ioe) {
return null;
}
}
- return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
} else {
- return ParcelFileDescriptor.open(
- getFile(dbName, id),
- ParcelFileDescriptor.MODE_READ_ONLY);
+ file = getFile(accountUuid, attachmentId);
}
+
+ return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
@Override
From c6696f632a18a3292f2edc7ee0650154e148fb73 Mon Sep 17 00:00:00 2001
From: cketti
Date: Tue, 24 Jan 2012 14:49:08 +0100
Subject: [PATCH 03/15] Code cleanup, fixed some warnings, rearranged some
stuff
---
.../fsck/k9/provider/AttachmentProvider.java | 168 +++++++++---------
1 file changed, 88 insertions(+), 80 deletions(-)
diff --git a/src/com/fsck/k9/provider/AttachmentProvider.java b/src/com/fsck/k9/provider/AttachmentProvider.java
index 1a493a446..4b90305c7 100644
--- a/src/com/fsck/k9/provider/AttachmentProvider.java
+++ b/src/com/fsck/k9/provider/AttachmentProvider.java
@@ -23,8 +23,12 @@ import java.io.*;
import java.util.List;
/**
- * A simple ContentProvider that allows file access to Email's attachments.
- * Warning! We make heavy assumptions about the Uris used by the {@link LocalStore} for an {@link Account} here.
+ * A simple ContentProvider that allows file access to attachments.
+ *
+ *
+ * Warning! We make heavy assumptions about the Uris used by the {@link LocalStore} for an
+ * {@link Account} here.
+ *
*/
public class AttachmentProvider extends ContentProvider {
public static final Uri CONTENT_URI = Uri.parse("content://com.fsck.k9.attachmentprovider");
@@ -33,6 +37,11 @@ public class AttachmentProvider extends ContentProvider {
private static final String FORMAT_VIEW = "VIEW";
private static final String FORMAT_THUMBNAIL = "THUMBNAIL";
+ private static final String[] DEFAULT_PROJECTION = new String[] {
+ AttachmentProviderColumns._ID,
+ AttachmentProviderColumns.DATA,
+ };
+
public static class AttachmentProviderColumns {
public static final String _ID = "_id";
public static final String DATA = "_data";
@@ -40,6 +49,7 @@ public class AttachmentProvider extends ContentProvider {
public static final String SIZE = "_size";
}
+
public static Uri getAttachmentUri(Account account, long id) {
return getAttachmentUri(account.getUuid(), id, true);
}
@@ -66,6 +76,23 @@ public class AttachmentProvider extends ContentProvider {
.build();
}
+ public static void clear(Context context) {
+ /*
+ * We use the cache dir as a temporary directory (since Android doesn't give us one) so
+ * on startup we'll clean up any .tmp files from the last run.
+ */
+ File[] files = context.getCacheDir().listFiles();
+ for (File file : files) {
+ try {
+ if (K9.DEBUG) {
+ Log.d(K9.LOG_TAG, "Deleting file " + file.getCanonicalPath());
+ }
+ } catch (IOException ioe) { /* No need to log failure to log */ }
+ file.delete();
+ }
+ }
+
+
@Override
public boolean onCreate() {
/*
@@ -89,21 +116,6 @@ public class AttachmentProvider extends ContentProvider {
return true;
}
- public static void clear(Context lContext) {
- /*
- * We use the cache dir as a temporary directory (since Android doesn't give us one) so
- * on startup we'll clean up any .tmp files from the last run.
- */
- File[] files = lContext.getCacheDir().listFiles();
- for (File file : files) {
- try {
- if (K9.DEBUG)
- Log.d(K9.LOG_TAG, "Deleting file " + file.getCanonicalPath());
- } catch (IOException ioe) {} // No need to log failure to log
- file.delete();
- }
- }
-
@Override
public String getType(Uri uri) {
List segments = uri.getPathSegments();
@@ -114,47 +126,6 @@ public class AttachmentProvider extends ContentProvider {
return getType(dbName, id, format);
}
- private String getType(String dbName, String id, String format) {
- if (FORMAT_THUMBNAIL.equals(format)) {
- return "image/png";
- } else {
- final Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
-
- try {
- final LocalStore localStore = LocalStore.getLocalInstance(account, K9.app);
-
- AttachmentInfo attachmentInfo = localStore.getAttachmentInfo(id);
- if (FORMAT_VIEW.equals(format)) {
- return MimeUtility.getMimeTypeForViewing(attachmentInfo.type, attachmentInfo.name);
- } else {
- // When accessing the "raw" message we deliver the original MIME type.
- return attachmentInfo.type;
- }
- } catch (MessagingException e) {
- Log.e(K9.LOG_TAG, "Unable to retrieve LocalStore for " + account, e);
- return null;
- }
- }
- }
-
- private File getFile(String dbName, String id)
- throws FileNotFoundException {
- try {
- final Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
- final File attachmentsDir;
- attachmentsDir = StorageManager.getInstance(K9.app).getAttachmentDirectory(dbName,
- account.getLocalStorageProviderId());
- final File file = new File(attachmentsDir, id);
- if (!file.exists()) {
- throw new FileNotFoundException(file.getAbsolutePath());
- }
- return file;
- } catch (IOException e) {
- Log.w(K9.LOG_TAG, null, e);
- throw new FileNotFoundException(e.getMessage());
- }
- }
-
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
File file;
@@ -200,26 +171,11 @@ public class AttachmentProvider extends ContentProvider {
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
}
- @Override
- public int delete(Uri uri, String arg1, String[] arg2) {
- return 0;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- return null;
- }
-
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
- if (projection == null) {
- projection =
- new String[] {
- AttachmentProviderColumns._ID,
- AttachmentProviderColumns.DATA,
- };
- }
+
+ String[] columnNames = (projection == null) ? DEFAULT_PROJECTION : projection;
List segments = uri.getPathSegments();
String dbName = segments.get(0);
@@ -231,7 +187,6 @@ public class AttachmentProvider extends ContentProvider {
dbName = dbName.substring(0, dbName.length() - 3);
}
- //String format = segments.get(2);
final AttachmentInfo attachmentInfo;
try {
final Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
@@ -241,10 +196,10 @@ public class AttachmentProvider extends ContentProvider {
return null;
}
- MatrixCursor ret = new MatrixCursor(projection);
- Object[] values = new Object[projection.length];
- for (int i = 0, count = projection.length; i < count; i++) {
- String column = projection[i];
+ MatrixCursor ret = new MatrixCursor(columnNames);
+ Object[] values = new Object[columnNames.length];
+ for (int i = 0, count = columnNames.length; i < count; i++) {
+ String column = columnNames[i];
if (AttachmentProviderColumns._ID.equals(column)) {
values[i] = id;
} else if (AttachmentProviderColumns.DATA.equals(column)) {
@@ -264,6 +219,59 @@ public class AttachmentProvider extends ContentProvider {
return 0;
}
+ @Override
+ public int delete(Uri uri, String arg1, String[] arg2) {
+ return 0;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ private String getType(String dbName, String id, String format) {
+ String type;
+ if (FORMAT_THUMBNAIL.equals(format)) {
+ type = "image/png";
+ } else {
+ final Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
+
+ try {
+ final LocalStore localStore = LocalStore.getLocalInstance(account, K9.app);
+
+ AttachmentInfo attachmentInfo = localStore.getAttachmentInfo(id);
+ if (FORMAT_VIEW.equals(format)) {
+ type = MimeUtility.getMimeTypeForViewing(attachmentInfo.type, attachmentInfo.name);
+ } else {
+ // When accessing the "raw" message we deliver the original MIME type.
+ type = attachmentInfo.type;
+ }
+ } catch (MessagingException e) {
+ Log.e(K9.LOG_TAG, "Unable to retrieve LocalStore for " + account, e);
+ type = null;
+ }
+ }
+
+ return type;
+ }
+
+ private File getFile(String dbName, String id) throws FileNotFoundException {
+ try {
+ final Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
+ final File attachmentsDir;
+ attachmentsDir = StorageManager.getInstance(K9.app).getAttachmentDirectory(dbName,
+ account.getLocalStorageProviderId());
+ final File file = new File(attachmentsDir, id);
+ if (!file.exists()) {
+ throw new FileNotFoundException(file.getAbsolutePath());
+ }
+ return file;
+ } catch (IOException e) {
+ Log.w(K9.LOG_TAG, null, e);
+ throw new FileNotFoundException(e.getMessage());
+ }
+ }
+
private Bitmap createThumbnail(String type, InputStream data) {
if (MimeUtility.mimeTypeMatches(type, "image/*")) {
return createImageThumbnail(data);
From 4e5d1167138869d42276c7e4114de12c4a31f5ee Mon Sep 17 00:00:00 2001
From: cketti
Date: Tue, 24 Jan 2012 15:41:03 +0100
Subject: [PATCH 04/15] Delete attachment metadata and thumbnails when deleting
attachments
---
src/com/fsck/k9/mail/store/LocalStore.java | 28 +++++++++++++------
.../fsck/k9/provider/AttachmentProvider.java | 28 +++++++++++++++++--
2 files changed, 45 insertions(+), 11 deletions(-)
diff --git a/src/com/fsck/k9/mail/store/LocalStore.java b/src/com/fsck/k9/mail/store/LocalStore.java
index abfa3ed1d..38130c509 100644
--- a/src/com/fsck/k9/mail/store/LocalStore.java
+++ b/src/com/fsck/k9/mail/store/LocalStore.java
@@ -2692,22 +2692,34 @@ public class LocalStore extends Store implements Serializable {
public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
Cursor attachmentsCursor = null;
try {
- attachmentsCursor = db.query("attachments", new String[]
- { "id" }, "message_id = ?", new String[]
- { Long.toString(messageId) }, null, null, null);
+ String accountUuid = mAccount.getUuid();
+ Context context = mApplication;
+
+ // Get attachment IDs
+ String[] whereArgs = new String[] { Long.toString(messageId) };
+ attachmentsCursor = db.query("attachments", new String[] { "id" },
+ "message_id = ?", whereArgs, null, null, null);
+
final File attachmentDirectory = StorageManager.getInstance(mApplication)
- .getAttachmentDirectory(uUid, database.getStorageProviderId());
+ .getAttachmentDirectory(uUid, database.getStorageProviderId());
+
while (attachmentsCursor.moveToNext()) {
- long attachmentId = attachmentsCursor.getLong(0);
+ String attachmentId = Long.toString(attachmentsCursor.getLong(0));
try {
- File file = new File(attachmentDirectory, Long.toString(attachmentId));
+ // Delete stored attachment
+ File file = new File(attachmentDirectory, attachmentId);
if (file.exists()) {
file.delete();
}
- } catch (Exception e) {
- }
+ // Delete thumbnail file
+ AttachmentProvider.deleteThumbnail(context, accountUuid,
+ attachmentId);
+ } catch (Exception e) { /* ignore */ }
}
+
+ // Delete attachment metadata from the database
+ db.delete("attachments", "message_id = ?", whereArgs);
} finally {
Utility.closeQuietly(attachmentsCursor);
}
diff --git a/src/com/fsck/k9/provider/AttachmentProvider.java b/src/com/fsck/k9/provider/AttachmentProvider.java
index 4b90305c7..dd380e6af 100644
--- a/src/com/fsck/k9/provider/AttachmentProvider.java
+++ b/src/com/fsck/k9/provider/AttachmentProvider.java
@@ -92,6 +92,30 @@ public class AttachmentProvider extends ContentProvider {
}
}
+ /**
+ * Delete the thumbnail of an attachment.
+ *
+ * @param context
+ * The application context.
+ * @param accountUuid
+ * The UUID of the account the attachment belongs to.
+ * @param attachmentId
+ * The ID of the attachment the thumbnail was created for.
+ */
+ public static void deleteThumbnail(Context context, String accountUuid, String attachmentId) {
+ File file = getThumbnailFile(context, accountUuid, attachmentId);
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+
+ private static File getThumbnailFile(Context context, String accountUuid,
+ String attachmentId) {
+ String filename = "thmb_" + accountUuid + "_" + attachmentId + ".tmp";
+ File dir = context.getCacheDir();
+ return new File(dir, filename);
+ }
+
@Override
public boolean onCreate() {
@@ -139,9 +163,7 @@ public class AttachmentProvider extends ContentProvider {
int width = Integer.parseInt(segments.get(3));
int height = Integer.parseInt(segments.get(4));
- String filename = "thmb_" + accountUuid + "_" + attachmentId + ".tmp";
- File dir = getContext().getCacheDir();
- file = new File(dir, filename);
+ file = getThumbnailFile(getContext(), accountUuid, attachmentId);
if (!file.exists()) {
String type = getType(accountUuid, attachmentId, FORMAT_VIEW);
try {
From aae734c175b630db9654ec221b1210f772a02397 Mon Sep 17 00:00:00 2001
From: cketti
Date: Tue, 24 Jan 2012 22:14:21 +0100
Subject: [PATCH 05/15] Don't Log.w() full stacktrace if file wasn't found
This happens regularly when AttachmentView tries to get a thumbnail for
attachments that haven't been downloaded yet.
---
.../fsck/k9/provider/AttachmentProvider.java | 23 ++++++++-----------
1 file changed, 10 insertions(+), 13 deletions(-)
diff --git a/src/com/fsck/k9/provider/AttachmentProvider.java b/src/com/fsck/k9/provider/AttachmentProvider.java
index dd380e6af..ec81e30ba 100644
--- a/src/com/fsck/k9/provider/AttachmentProvider.java
+++ b/src/com/fsck/k9/provider/AttachmentProvider.java
@@ -278,20 +278,17 @@ public class AttachmentProvider extends ContentProvider {
}
private File getFile(String dbName, String id) throws FileNotFoundException {
- try {
- final Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
- final File attachmentsDir;
- attachmentsDir = StorageManager.getInstance(K9.app).getAttachmentDirectory(dbName,
- account.getLocalStorageProviderId());
- final File file = new File(attachmentsDir, id);
- if (!file.exists()) {
- throw new FileNotFoundException(file.getAbsolutePath());
- }
- return file;
- } catch (IOException e) {
- Log.w(K9.LOG_TAG, null, e);
- throw new FileNotFoundException(e.getMessage());
+ Account account = Preferences.getPreferences(getContext()).getAccount(dbName);
+
+ File attachmentsDir = StorageManager.getInstance(K9.app).getAttachmentDirectory(dbName,
+ account.getLocalStorageProviderId());
+
+ File file = new File(attachmentsDir, id);
+ if (!file.exists()) {
+ throw new FileNotFoundException(file.getAbsolutePath());
}
+
+ return file;
}
private Bitmap createThumbnail(String type, InputStream data) {
From 5a8ddaa039ae325bb80f1cc3542f497bd2e5415d Mon Sep 17 00:00:00 2001
From: cketti
Date: Thu, 26 Jan 2012 00:37:25 +0100
Subject: [PATCH 06/15] Make sure draft id points to a valid message before
deleting it
Avoids IllegalArgumentException in LocalStore.getMessage()
---
src/com/fsck/k9/activity/MessageCompose.java | 5 +++--
src/com/fsck/k9/controller/MessagingController.java | 8 +++++---
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/com/fsck/k9/activity/MessageCompose.java b/src/com/fsck/k9/activity/MessageCompose.java
index 6da95c263..2eac71f19 100644
--- a/src/com/fsck/k9/activity/MessageCompose.java
+++ b/src/com/fsck/k9/activity/MessageCompose.java
@@ -2988,9 +2988,10 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
}
MessagingController.getInstance(getApplication()).sendMessage(mAccount, message, null);
- if (mDraftId != INVALID_DRAFT_ID) {
- MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftId);
+ long draftId = mDraftId;
+ if (draftId != INVALID_DRAFT_ID) {
mDraftId = INVALID_DRAFT_ID;
+ MessagingController.getInstance(getApplication()).deleteDraft(mAccount, draftId);
}
return null;
diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java
index 2aaa48ae1..b3b6b5462 100644
--- a/src/com/fsck/k9/controller/MessagingController.java
+++ b/src/com/fsck/k9/controller/MessagingController.java
@@ -3311,9 +3311,11 @@ public class MessagingController implements Runnable {
localFolder = localStore.getFolder(account.getDraftsFolderName());
localFolder.open(OpenMode.READ_WRITE);
String uid = localFolder.getMessageUidById(id);
- Message message = localFolder.getMessage(uid);
- if (message != null) {
- deleteMessages(new Message[] { message }, null);
+ if (uid != null) {
+ Message message = localFolder.getMessage(uid);
+ if (message != null) {
+ deleteMessages(new Message[] { message }, null);
+ }
}
} catch (MessagingException me) {
addErrorMessage(account, null, me);
From e8eae3738963cc5f14c8750197fea1423e8818e1 Mon Sep 17 00:00:00 2001
From: cketti
Date: Fri, 27 Jan 2012 00:51:18 +0100
Subject: [PATCH 07/15] Reset unread/flagged count on "empty trash"
---
src/com/fsck/k9/controller/MessagingController.java | 5 +++--
src/com/fsck/k9/mail/store/LocalStore.java | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java
index b3b6b5462..389e6f2a4 100644
--- a/src/com/fsck/k9/controller/MessagingController.java
+++ b/src/com/fsck/k9/controller/MessagingController.java
@@ -3470,12 +3470,13 @@ public class MessagingController implements Runnable {
putBackground("emptyTrash", listener, new Runnable() {
@Override
public void run() {
- Folder localFolder = null;
+ LocalFolder localFolder = null;
try {
Store localStore = account.getLocalStore();
- localFolder = localStore.getFolder(account.getTrashFolderName());
+ localFolder = (LocalFolder) localStore.getFolder(account.getTrashFolderName());
localFolder.open(OpenMode.READ_WRITE);
localFolder.setFlags(new Flag[] { Flag.DELETED }, true);
+ localFolder.resetUnreadAndFlaggedCounts();
for (MessagingListener l : getListeners()) {
l.emptyTrashCompleted(account);
diff --git a/src/com/fsck/k9/mail/store/LocalStore.java b/src/com/fsck/k9/mail/store/LocalStore.java
index 38130c509..049f4222e 100644
--- a/src/com/fsck/k9/mail/store/LocalStore.java
+++ b/src/com/fsck/k9/mail/store/LocalStore.java
@@ -2619,7 +2619,7 @@ public class LocalStore extends Store implements Serializable {
setVisibleLimit(mAccount.getDisplayCount());
}
- private void resetUnreadAndFlaggedCounts() {
+ public void resetUnreadAndFlaggedCounts() {
try {
int newUnread = 0;
int newFlagged = 0;
From 193450cd63086e11b4822b3b3b13d663a47c1bb3 Mon Sep 17 00:00:00 2001
From: wilian-cb
Date: Thu, 26 Jan 2012 19:25:46 -0200
Subject: [PATCH 08/15] 3674: Illegal characters used in file names are being
removed when saving them on the device.
---
src/com/fsck/k9/view/AttachmentView.java | 24 ++++++++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/src/com/fsck/k9/view/AttachmentView.java b/src/com/fsck/k9/view/AttachmentView.java
index 9e9a4c441..764663cbe 100644
--- a/src/com/fsck/k9/view/AttachmentView.java
+++ b/src/com/fsck/k9/view/AttachmentView.java
@@ -52,6 +52,13 @@ public class AttachmentView extends FrameLayout {
public String contentType;
public long size;
public ImageView iconView;
+
+ /**
+ * Regular expression that represents characters that aren't allowed
+ * to be used in file names saved using K-9
+ */
+ private static final String specialCharacters = new String("[^\\d\\s\\w!" +
+ "#\\$%&'\\(\\)\\-@\\^_`\\{\\}~.,]");
private AttachmentFileDownloadCallback callback;
@@ -196,7 +203,8 @@ public class AttachmentView extends FrameLayout {
*/
public void writeFile(File directory) {
try {
- File file = Utility.createUniqueFile(directory, name);
+ String filename = removeSpecialCharacters(name);
+ File file = Utility.createUniqueFile(directory, filename);
Uri uri = AttachmentProvider.getAttachmentUri(mAccount, part.getAttachmentId());
InputStream in = mContext.getContentResolver().openInputStream(uri);
OutputStream out = new FileOutputStream(file);
@@ -204,12 +212,24 @@ public class AttachmentView extends FrameLayout {
out.flush();
out.close();
in.close();
- attachmentSaved(file.toString());
+ attachmentSaved(filename.toString());
new MediaScannerNotifier(mContext, file);
} catch (IOException ioe) {
attachmentNotSaved();
}
}
+
+ /**
+ * Removes characters that aren't allowed to be used in file names saved
+ * in K-9 application.
+ *
+ * @param filename The original file name.
+ * @return A file name with only legal characters.
+ */
+ private String removeSpecialCharacters(String filename) {
+ return filename.replaceAll(specialCharacters, "");
+ }
+
/**
* saves the file to the defaultpath setting in the config, or if the config
* is not set => to the Environment
From 9a0f650cd95c93e59f7b21ee38892c26b4d2e9ff Mon Sep 17 00:00:00 2001
From: wilian-cb
Date: Thu, 26 Jan 2012 20:53:41 -0200
Subject: [PATCH 09/15] 3674: Displaying the final file name.
---
src/com/fsck/k9/view/AttachmentView.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/com/fsck/k9/view/AttachmentView.java b/src/com/fsck/k9/view/AttachmentView.java
index 764663cbe..7525456fd 100644
--- a/src/com/fsck/k9/view/AttachmentView.java
+++ b/src/com/fsck/k9/view/AttachmentView.java
@@ -212,7 +212,7 @@ public class AttachmentView extends FrameLayout {
out.flush();
out.close();
in.close();
- attachmentSaved(filename.toString());
+ attachmentSaved(file.toString());
new MediaScannerNotifier(mContext, file);
} catch (IOException ioe) {
attachmentNotSaved();
From 68f5f009f1548efbcb87c4cb837d1201eeaf761c Mon Sep 17 00:00:00 2001
From: cketti
Date: Fri, 27 Jan 2012 03:07:44 +0100
Subject: [PATCH 10/15] Whitespace cleanup
---
src/com/fsck/k9/view/AttachmentView.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/com/fsck/k9/view/AttachmentView.java b/src/com/fsck/k9/view/AttachmentView.java
index 7525456fd..0a851e658 100644
--- a/src/com/fsck/k9/view/AttachmentView.java
+++ b/src/com/fsck/k9/view/AttachmentView.java
@@ -52,13 +52,13 @@ public class AttachmentView extends FrameLayout {
public String contentType;
public long size;
public ImageView iconView;
-
+
/**
* Regular expression that represents characters that aren't allowed
* to be used in file names saved using K-9
*/
private static final String specialCharacters = new String("[^\\d\\s\\w!" +
- "#\\$%&'\\(\\)\\-@\\^_`\\{\\}~.,]");
+ "#\\$%&'\\(\\)\\-@\\^_`\\{\\}~.,]");
private AttachmentFileDownloadCallback callback;
@@ -222,12 +222,12 @@ public class AttachmentView extends FrameLayout {
/**
* Removes characters that aren't allowed to be used in file names saved
* in K-9 application.
- *
+ *
* @param filename The original file name.
* @return A file name with only legal characters.
*/
private String removeSpecialCharacters(String filename) {
- return filename.replaceAll(specialCharacters, "");
+ return filename.replaceAll(specialCharacters, "");
}
/**
From 6c23e204baa21d74bec9a6099956061da58116e8 Mon Sep 17 00:00:00 2001
From: cketti
Date: Fri, 27 Jan 2012 03:21:20 +0100
Subject: [PATCH 11/15] Replace invalid characters in file name instead of
removing them
---
src/com/fsck/k9/view/AttachmentView.java | 34 ++++++++++++++----------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/src/com/fsck/k9/view/AttachmentView.java b/src/com/fsck/k9/view/AttachmentView.java
index 0a851e658..8621aa7a9 100644
--- a/src/com/fsck/k9/view/AttachmentView.java
+++ b/src/com/fsck/k9/view/AttachmentView.java
@@ -39,6 +39,18 @@ import com.fsck.k9.mail.store.LocalStore.LocalAttachmentBodyPart;
import com.fsck.k9.provider.AttachmentProvider;
public class AttachmentView extends FrameLayout {
+ /**
+ * Regular expression that represents characters that aren't allowed
+ * to be used in file names saved using K-9
+ */
+ private static final String INVALID_CHARACTERS = "[^\\d\\s\\w!" +
+ "#\\$%&'\\(\\)\\-@\\^_`\\{\\}~.,]+";
+
+ /**
+ * Invalid characters in a file name are replaced by this character.
+ */
+ private static final String REPLACEMENT_CHARACTER = "_";
+
private Context mContext;
public Button viewButton;
@@ -53,13 +65,6 @@ public class AttachmentView extends FrameLayout {
public long size;
public ImageView iconView;
- /**
- * Regular expression that represents characters that aren't allowed
- * to be used in file names saved using K-9
- */
- private static final String specialCharacters = new String("[^\\d\\s\\w!" +
- "#\\$%&'\\(\\)\\-@\\^_`\\{\\}~.,]");
-
private AttachmentFileDownloadCallback callback;
public AttachmentView(Context context, AttributeSet attrs, int defStyle) {
@@ -203,7 +208,7 @@ public class AttachmentView extends FrameLayout {
*/
public void writeFile(File directory) {
try {
- String filename = removeSpecialCharacters(name);
+ String filename = sanitizeFilename(name);
File file = Utility.createUniqueFile(directory, filename);
Uri uri = AttachmentProvider.getAttachmentUri(mAccount, part.getAttachmentId());
InputStream in = mContext.getContentResolver().openInputStream(uri);
@@ -220,14 +225,15 @@ public class AttachmentView extends FrameLayout {
}
/**
- * Removes characters that aren't allowed to be used in file names saved
- * in K-9 application.
+ * Replace characters we don't allow in file names with a replacement character.
*
- * @param filename The original file name.
- * @return A file name with only legal characters.
+ * @param filename
+ * The original file name.
+ *
+ * @return The sanitized file name containing only allowed characters.
*/
- private String removeSpecialCharacters(String filename) {
- return filename.replaceAll(specialCharacters, "");
+ private String sanitizeFilename(String filename) {
+ return filename.replaceAll(INVALID_CHARACTERS, REPLACEMENT_CHARACTER);
}
/**
From 1165787129e27877f4d61099d9e41e490b9886a4 Mon Sep 17 00:00:00 2001
From: cketti
Date: Fri, 27 Jan 2012 03:39:08 +0100
Subject: [PATCH 12/15] Changed regular expression for invalid characters in a
file name
---
src/com/fsck/k9/view/AttachmentView.java | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/com/fsck/k9/view/AttachmentView.java b/src/com/fsck/k9/view/AttachmentView.java
index 8621aa7a9..bb736f6cc 100644
--- a/src/com/fsck/k9/view/AttachmentView.java
+++ b/src/com/fsck/k9/view/AttachmentView.java
@@ -40,11 +40,19 @@ import com.fsck.k9.provider.AttachmentProvider;
public class AttachmentView extends FrameLayout {
/**
- * Regular expression that represents characters that aren't allowed
- * to be used in file names saved using K-9
+ * Regular expression that represents characters we won't allow in file names.
+ *
+ *
+ * Allowed are:
+ *
+ * - word characters (letters, digits, and underscores): {@code \w}
+ * - spaces: {@code " "}
+ * - special characters: {@code !}, {@code #}, {@code $}, {@code %}, {@code &}, {@code '},
+ * {@code (}, {@code )}, {@code -}, {@code @}, {@code ^}, {@code `},
{
,
+ * }
, {@code ~}, {@code .}, {@code ,}
+ *
*/
- private static final String INVALID_CHARACTERS = "[^\\d\\s\\w!" +
- "#\\$%&'\\(\\)\\-@\\^_`\\{\\}~.,]+";
+ private static final String INVALID_CHARACTERS = "[^\\w !#$%&'()\\-@\\^`{}~.,]+";
/**
* Invalid characters in a file name are replaced by this character.
From b1a1de8f7b829e8a07e74c5e79eeb1b29bb19d42 Mon Sep 17 00:00:00 2001
From: cketti
Date: Fri, 27 Jan 2012 08:39:10 +0100
Subject: [PATCH 13/15] Restore mark as unread in message view
Fixes issue 3958
Fixes issue 3319
---
src/com/fsck/k9/activity/MessageView.java | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/com/fsck/k9/activity/MessageView.java b/src/com/fsck/k9/activity/MessageView.java
index fb6afcc60..64f4c9208 100644
--- a/src/com/fsck/k9/activity/MessageView.java
+++ b/src/com/fsck/k9/activity/MessageView.java
@@ -20,6 +20,7 @@ import com.fsck.k9.crypto.PgpData;
import com.fsck.k9.helper.FileBrowserHelper;
import com.fsck.k9.helper.FileBrowserHelper.FileBrowserFailOverCallback;
import com.fsck.k9.mail.*;
+import com.fsck.k9.mail.store.LocalStore.LocalMessage;
import com.fsck.k9.mail.store.StorageManager;
import com.fsck.k9.view.AttachmentView;
import com.fsck.k9.view.ToggleScrollView;
@@ -726,10 +727,15 @@ public class MessageView extends K9Activity implements OnClickListener {
private void onFlag() {
if (mMessage != null) {
- mController.setFlag(mAccount,
- mMessage.getFolder().getName(), new String[] {mMessage.getUid()}, Flag.FLAGGED, !mMessage.isSet(Flag.FLAGGED));
+ boolean newState = !mMessage.isSet(Flag.FLAGGED);
+ mController.setFlag(mAccount, mMessage.getFolder().getName(),
+ new String[] {mMessage.getUid()}, Flag.FLAGGED, newState);
try {
- mMessage.setFlag(Flag.FLAGGED, !mMessage.isSet(Flag.FLAGGED));
+ // FIXME: This is a hack to change the flagged state of our message object. We
+ // can't call Message.setFlag() because that would "adjust" the flagged count
+ // another time (first time by MessagingController.setFlag(...)).
+ ((LocalMessage)mMessage).setFlagInternal(Flag.FLAGGED, newState);
+
mMessageView.setHeaders(mMessage, mAccount);
} catch (MessagingException me) {
Log.e(K9.LOG_TAG, "Could not set flag on local message", me);
@@ -876,9 +882,13 @@ public class MessageView extends K9Activity implements OnClickListener {
private void onMarkAsUnread() {
if (mMessage != null) {
-// (Issue 3319) mController.setFlag(mAccount, mMessageReference.folderName, new String[] { mMessage.getUid() }, Flag.SEEN, false);
+ mController.setFlag(mAccount, mMessage.getFolder().getName(),
+ new String[] { mMessage.getUid() }, Flag.SEEN, false);
try {
- mMessage.setFlag(Flag.SEEN, false);
+ // FIXME: This is a hack to mark our message object as unread. We can't call
+ // Message.setFlag() because that would "adjust" the unread count twice.
+ ((LocalMessage)mMessage).setFlagInternal(Flag.SEEN, false);
+
mMessageView.setHeaders(mMessage, mAccount);
String subject = mMessage.getSubject();
setTitle(subject);
From 35b5aebdb322fa44e2c8173dbd9a5f5ef3c51c36 Mon Sep 17 00:00:00 2001
From: cketti
Date: Fri, 3 Feb 2012 01:22:37 +0100
Subject: [PATCH 14/15] Add debug message when saving an attachment to SD card
fails
---
src/com/fsck/k9/view/AttachmentView.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/com/fsck/k9/view/AttachmentView.java b/src/com/fsck/k9/view/AttachmentView.java
index bb736f6cc..f581c3db2 100644
--- a/src/com/fsck/k9/view/AttachmentView.java
+++ b/src/com/fsck/k9/view/AttachmentView.java
@@ -228,6 +228,9 @@ public class AttachmentView extends FrameLayout {
attachmentSaved(file.toString());
new MediaScannerNotifier(mContext, file);
} catch (IOException ioe) {
+ if (K9.DEBUG) {
+ Log.e(K9.LOG_TAG, "Error saving attachment", ioe);
+ }
attachmentNotSaved();
}
}
From 46bf2c5be7e9d3097da736d8448ddd325aae8702 Mon Sep 17 00:00:00 2001
From: Nick Nikolaou
Date: Thu, 2 Feb 2012 21:56:56 +0000
Subject: [PATCH 15/15] Add discard confirmation dialog when pressing back
---
res/values/strings.xml | 3 ++
src/com/fsck/k9/activity/MessageCompose.java | 42 +++++++++++++++++---
2 files changed, 39 insertions(+), 6 deletions(-)
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f2666ff53..9fd5973aa 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1030,6 +1030,9 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin
Save draft message?
Save or Discard this message?
+ Discard message?
+ Are you sure you want to discard this message?
+
Refuse to save draft message.
Refuse to save draft message marked encrypted.
diff --git a/src/com/fsck/k9/activity/MessageCompose.java b/src/com/fsck/k9/activity/MessageCompose.java
index 2eac71f19..a24423eb3 100644
--- a/src/com/fsck/k9/activity/MessageCompose.java
+++ b/src/com/fsck/k9/activity/MessageCompose.java
@@ -83,6 +83,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private static final int DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE = 1;
private static final int DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED = 2;
private static final int DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY = 3;
+ private static final int DIALOG_CONFIRM_DISCARD_ON_BACK = 4;
private static final long INVALID_DRAFT_ID = MessagingController.INVALID_MESSAGE_ID;
@@ -2051,13 +2052,21 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
@Override
public void onBackPressed() {
- if (mEncryptCheckbox.isChecked()) {
- showDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
- } else if (!mDraftNeedsSaving || isDraftsFolderDisabled()) {
- Toast.makeText(MessageCompose.this, getString(R.string.message_discarded_toast), Toast.LENGTH_LONG).show();
- super.onBackPressed();
+ if (mDraftNeedsSaving) {
+ if (mEncryptCheckbox.isChecked()) {
+ showDialog(DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED);
+ } else if (isDraftsFolderDisabled()) {
+ showDialog(DIALOG_CONFIRM_DISCARD_ON_BACK);
+ } else {
+ showDialog(DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE);
+ }
} else {
- showDialog(DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE);
+ // Check if editing an existing draft.
+ if (mDraftId == INVALID_DRAFT_ID) {
+ onDiscard();
+ } else {
+ super.onBackPressed();
+ }
}
}
@@ -2118,6 +2127,27 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
}
})
.create();
+ case DIALOG_CONFIRM_DISCARD_ON_BACK:
+ return new AlertDialog.Builder(this)
+ .setTitle(R.string.confirm_discard_draft_message_title)
+ .setMessage(R.string.confirm_discard_draft_message)
+ .setPositiveButton(R.string.cancel_action, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ dismissDialog(DIALOG_CONFIRM_DISCARD_ON_BACK);
+ }
+ })
+ .setNegativeButton(R.string.discard_action, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int whichButton) {
+ dismissDialog(DIALOG_CONFIRM_DISCARD_ON_BACK);
+ Toast.makeText(MessageCompose.this,
+ getString(R.string.message_discarded_toast),
+ Toast.LENGTH_LONG).show();
+ onDiscard();
+ }
+ })
+ .create();
}
return super.onCreateDialog(id);
}