diff --git a/res/values/strings.xml b/res/values/strings.xml index a596a534a..4b7569009 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -242,6 +242,7 @@ finding key... decompressing data... verifying integrity... + deleting \'%s\' securely... Read key details from APG. diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java index 5983bef1b..725136ef2 100644 --- a/src/org/thialfihar/android/apg/Apg.java +++ b/src/org/thialfihar/android/apg/Apg.java @@ -20,10 +20,12 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; +import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.RandomAccessFile; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPairGenerator; @@ -1895,4 +1897,24 @@ public class Apg { } return size; } + + static void deleteFileSecurely(Context context, File file, ProgressDialogUpdater progress) + throws FileNotFoundException, IOException { + long length = file.length(); + SecureRandom random = new SecureRandom(); + RandomAccessFile raf = new RandomAccessFile(file, "rws"); + raf.seek(0); + raf.getFilePointer(); + byte[] data = new byte[1 << 16]; + int pos = 0; + String msg = context.getString(R.string.progress_deletingSecurely, file.getName()); + while (pos < length) { + progress.setProgress(msg, (int)(100 * pos / length), 100); + random.nextBytes(data); + raf.write(data); + pos += data.length; + } + raf.close(); + file.delete(); + } } diff --git a/src/org/thialfihar/android/apg/BaseActivity.java b/src/org/thialfihar/android/apg/BaseActivity.java index 4a0360b25..bea8f1caf 100644 --- a/src/org/thialfihar/android/apg/BaseActivity.java +++ b/src/org/thialfihar/android/apg/BaseActivity.java @@ -17,6 +17,8 @@ package org.thialfihar.android.apg; import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.Locale; import android.app.Activity; @@ -44,6 +46,7 @@ public class BaseActivity extends Activity private ProgressDialog mProgressDialog = null; private Thread mRunningThread = null; + private Thread mDeletingThread = null; private long mSecretKeyId = 0; private String mDeleteFile = null; @@ -149,6 +152,11 @@ public class BaseActivity extends Activity return mProgressDialog; } + case Id.dialog.deleting: { + mProgressDialog.setMessage(this.getString(R.string.progress_initializing)); + return mProgressDialog; + } + default: { break; } @@ -235,19 +243,30 @@ public class BaseActivity extends Activity new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { removeDialog(Id.dialog.delete_file); - File file = new File(getDeleteFile()); - String msg = ""; - if (file.delete()) { - msg = BaseActivity.this.getString( - R.string.fileDeleteSuccessful); - } else { - msg = BaseActivity.this.getString( - R.string.errorMessage, - BaseActivity.this.getString( - R.string.error_fileDeleteFailed, file)); - } - Toast.makeText(BaseActivity.this, - msg, Toast.LENGTH_SHORT).show(); + final File file = new File(getDeleteFile()); + showDialog(Id.dialog.deleting); + mDeletingThread = new Thread(new Runnable() { + @Override + public void run() { + Bundle data = new Bundle(); + data.putInt(Apg.EXTRA_STATUS, Id.message.delete_done); + try { + Apg.deleteFileSecurely(BaseActivity.this, file, BaseActivity.this); + } catch (FileNotFoundException e) { + data.putString(Apg.EXTRA_ERROR, + BaseActivity.this.getString( + R.string.error_fileNotFound, file)); + } catch (IOException e) { + data.putString(Apg.EXTRA_ERROR, + BaseActivity.this.getString( + R.string.error_fileDeleteFailed, file)); + } + Message msg = new Message(); + msg.setData(data); + sendMessage(msg); + } + }); + mDeletingThread.start(); } }); alert.setNegativeButton(android.R.string.cancel, @@ -335,8 +354,14 @@ public class BaseActivity extends Activity break; } - case Id.message.import_done: // intentionall no break - case Id.message.export_done: // intentionall no break + case Id.message.delete_done: { + mProgressDialog = null; + deleteDoneCallback(msg); + break; + } + + case Id.message.import_done: // intentionally no break + case Id.message.export_done: // intentionally no break case Id.message.done: { mProgressDialog = null; doneCallback(msg); @@ -349,6 +374,22 @@ public class BaseActivity extends Activity } + public void deleteDoneCallback(Message msg) { + removeDialog(Id.dialog.deleting); + mDeletingThread = null; + + Bundle data = msg.getData(); + String error = data.getString(Apg.EXTRA_ERROR); + String message; + if (error != null) { + message = getString(R.string.errorMessage, error); + } else { + message = getString(R.string.fileDeleteSuccessful); + } + + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + } + public void passPhraseCallback(long keyId, String passPhrase) { Apg.setCachedPassPhrase(keyId, passPhrase); } diff --git a/src/org/thialfihar/android/apg/DecryptActivity.java b/src/org/thialfihar/android/apg/DecryptActivity.java index d8b7ccd9c..f5e35c584 100644 --- a/src/org/thialfihar/android/apg/DecryptActivity.java +++ b/src/org/thialfihar/android/apg/DecryptActivity.java @@ -545,8 +545,7 @@ public class DecryptActivity extends BaseActivity { String error = data.getString(Apg.EXTRA_ERROR); if (error != null) { - Toast.makeText(DecryptActivity.this, - getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show(); + Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show(); return; } diff --git a/src/org/thialfihar/android/apg/EncryptActivity.java b/src/org/thialfihar/android/apg/EncryptActivity.java index 4854f355c..5d69d8563 100644 --- a/src/org/thialfihar/android/apg/EncryptActivity.java +++ b/src/org/thialfihar/android/apg/EncryptActivity.java @@ -779,8 +779,7 @@ public class EncryptActivity extends BaseActivity { Bundle data = msg.getData(); String error = data.getString(Apg.EXTRA_ERROR); if (error != null) { - Toast.makeText(EncryptActivity.this, - getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show(); + Toast.makeText(this, getString(R.string.errorMessage, error), Toast.LENGTH_SHORT).show(); return; } switch (mEncryptTarget) { diff --git a/src/org/thialfihar/android/apg/Id.java b/src/org/thialfihar/android/apg/Id.java index 9ff484271..73ac39218 100644 --- a/src/org/thialfihar/android/apg/Id.java +++ b/src/org/thialfihar/android/apg/Id.java @@ -46,6 +46,7 @@ public final class Id { public static final int export_done = 0x21070006; public static final int create_key = 0x21070007; public static final int edit_key = 0x21070008; + public static final int delete_done = 0x21070009; } public static final class request { @@ -74,6 +75,7 @@ public final class Id { public static final int change_log = 0x21070010; public static final int output_filename = 0x21070011; public static final int delete_file = 0x21070012; + public static final int deleting = 0x21070013; } public static final class task {