aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Torlaschi <runnerway@gmail.com>2016-03-11 00:50:11 +0100
committerAndrea Torlaschi <runnerway@gmail.com>2016-03-27 18:20:29 +0200
commit360b5a658a412d9402a5fc9ea204329c91d306c3 (patch)
treeb5f4ea67bd27c9d22e69446f79415a37a2262cbc
parent0ce989ef1840a1a60cabf48d8bc5a00d5d3591f3 (diff)
downloadopen-keychain-360b5a658a412d9402a5fc9ea204329c91d306c3.tar.gz
open-keychain-360b5a658a412d9402a5fc9ea204329c91d306c3.tar.bz2
open-keychain-360b5a658a412d9402a5fc9ea204329c91d306c3.zip
Handle encrypted files while importing keys
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java15
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java103
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java27
-rw-r--r--OpenKeychain/src/main/res/values/strings.xml1
4 files changed, 136 insertions, 10 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index 72e42eec3..7d2d30c35 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -416,11 +416,18 @@ public class ImportKeysActivity extends BaseActivity
intent.putExtra(ImportKeyResult.EXTRA_RESULT, result);
setResult(RESULT_OK, intent);
finish();
- return;
+ } else if (result.isOkNew() || result.isOkUpdated()) {
+ // User has successfully imported a key, hide first time dialog
+ Preferences.getPreferences(this).setFirstTime(false);
+
+ // Close activities opened for importing keys and go to the list of keys
+ Intent intent = new Intent(this, MainActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ startActivity(intent);
+ } else {
+ result.createNotify(ImportKeysActivity.this)
+ .show((ViewGroup) findViewById(R.id.import_snackbar));
}
-
- result.createNotify(ImportKeysActivity.this)
- .show((ViewGroup) findViewById(R.id.import_snackbar));
}
// methods from CryptoOperationHelper.Callback
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
index 8de60dfd3..133cf299f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
@@ -17,29 +17,46 @@
package org.sufficientlysecure.keychain.ui;
+import android.Manifest;
import android.app.Activity;
+import android.content.ContentResolver;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
+import android.support.v4.content.ContextCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.pgp.PgpHelper;
+import org.sufficientlysecure.keychain.ui.ImportKeysListFragment.BytesLoaderState;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.FileHelper;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
public class ImportKeysFileFragment extends Fragment {
private ImportKeysActivity mImportActivity;
private View mBrowse;
private View mClipboardButton;
- public static final int REQUEST_CODE_FILE = 0x00007003;
+ private Uri mCurrentUri;
+
+ private static final int REQUEST_CODE_FILE = 0x00007003;
+ private static final int REQUEST_PERMISSION_READ_EXTERNAL_STORAGE = 12;
/**
* Creates new instance of this fragment
@@ -83,10 +100,10 @@ public class ImportKeysFileFragment extends Fragment {
sendText = clipboardText.toString();
sendText = PgpHelper.getPgpKeyContent(sendText);
if (sendText == null) {
- Notify.create(mImportActivity, "Bad data!", Style.ERROR).show();
+ Notify.create(mImportActivity, R.string.error_bad_data, Style.ERROR).show();
return;
}
- mImportActivity.loadCallback(new ImportKeysListFragment.BytesLoaderState(sendText.getBytes(), null));
+ mImportActivity.loadCallback(new BytesLoaderState(sendText.getBytes(), null));
}
}
});
@@ -106,11 +123,12 @@ public class ImportKeysFileFragment extends Fragment {
switch (requestCode) {
case REQUEST_CODE_FILE: {
if (resultCode == Activity.RESULT_OK && data != null && data.getData() != null) {
+ mCurrentUri = data.getData();
- // load data
- mImportActivity.loadCallback(new ImportKeysListFragment.BytesLoaderState(null, data.getData()));
+ if (checkAndRequestReadPermission(mCurrentUri)) {
+ startImportingKeys();
+ }
}
-
break;
}
@@ -121,4 +139,77 @@ public class ImportKeysFileFragment extends Fragment {
}
}
+ private void startImportingKeys() {
+ boolean isEncrypted;
+ try {
+ isEncrypted = FileHelper.isEncryptedFile(mImportActivity, mCurrentUri);
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "Error opening file", e);
+
+ Notify.create(mImportActivity, R.string.error_bad_data, Style.ERROR).show();
+ return;
+ }
+
+ if (isEncrypted) {
+ Intent intent = new Intent(mImportActivity, DecryptActivity.class);
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.setData(mCurrentUri);
+ startActivity(intent);
+ } else {
+ mImportActivity.loadCallback(new BytesLoaderState(null, mCurrentUri));
+ }
+ }
+
+ /**
+ * Request READ_EXTERNAL_STORAGE permission on Android >= 6.0 to read content from "file" Uris.
+ * <p/>
+ * This method returns true on Android < 6, or if permission is already granted. It
+ * requests the permission and returns false otherwise.
+ * <p/>
+ * see https://commonsware.com/blog/2015/10/07/runtime-permissions-files-action-send.html
+ */
+ private boolean checkAndRequestReadPermission(final Uri uri) {
+ if (!ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
+ return true;
+ }
+
+ // Additional check due to https://commonsware.com/blog/2015/11/09/you-cannot-hold-nonexistent-permissions.html
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
+ return true;
+ }
+
+ if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)
+ == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+
+ requestPermissions(
+ new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
+ REQUEST_PERMISSION_READ_EXTERNAL_STORAGE);
+
+ return false;
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode,
+ @NonNull String[] permissions,
+ @NonNull int[] grantResults) {
+
+ if (requestCode != REQUEST_PERMISSION_READ_EXTERNAL_STORAGE) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ return;
+ }
+
+ boolean permissionWasGranted = grantResults.length > 0
+ && grantResults[0] == PackageManager.PERMISSION_GRANTED;
+
+ if (permissionWasGranted) {
+ startImportingKeys();
+ } else {
+ Toast.makeText(getActivity(), R.string.error_denied_storage_permission, Toast.LENGTH_LONG).show();
+ getActivity().setResult(Activity.RESULT_CANCELED);
+ getActivity().finish();
+ }
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
index 106775201..62dd87baa 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/FileHelper.java
@@ -20,11 +20,13 @@ package org.sufficientlysecure.keychain.util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
@@ -223,6 +225,31 @@ public class FileHelper {
}
}
+ public static boolean isEncryptedFile(Context context, Uri uri) throws IOException {
+ boolean isEncrypted = false;
+
+ BufferedReader br = null;
+ try {
+ InputStream is = context.getContentResolver().openInputStream(uri);
+ br = new BufferedReader(new InputStreamReader(is));
+
+ String header = "-----BEGIN PGP MESSAGE-----";
+ int length = header.length();
+ char[] buffer = new char[length];
+ if (br.read(buffer, 0, length) == length) {
+ isEncrypted = new String(buffer).equals(header);
+ }
+ } finally {
+ try {
+ if (br != null)
+ br.close();
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "Error closing file", e);
+ }
+ }
+ return isEncrypted;
+ }
+
public static String readableFileSize(long size) {
if (size <= 0) return "0";
final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml
index c8a07c8ef..f9838ba72 100644
--- a/OpenKeychain/src/main/res/values/strings.xml
+++ b/OpenKeychain/src/main/res/values/strings.xml
@@ -359,6 +359,7 @@
<string name="error_file_delete_failed">"have not been deleted. Delete them manually!"</string>
<string name="error_file_added_already">%s has already been added.</string>
<string name="error_file_not_found">"file not found"</string>
+ <string name="error_bad_data">"Bad data!"</string>
<string name="error_no_secret_key_found">"no suitable secret key found"</string>
<string name="error_external_storage_not_ready">"external storage not ready"</string>
<string name="error_key_size_minimum512bit">"key size must be at least 512bit"</string>