diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/compatibility/ClipboardReflection.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/compatibility/ClipboardReflection.java index 0911068c5..eb550e3ef 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/compatibility/ClipboardReflection.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/compatibility/ClipboardReflection.java @@ -34,6 +34,9 @@ public class ClipboardReflection { return null; } ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + if (clipboard == null) { + return null; + } ClipData clip = clipboard.getPrimaryClip(); if (clip == null || clip.getItemCount() == 0) { @@ -48,4 +51,16 @@ public class ClipboardReflection { } return null; } + + public static void clearClipboard(@Nullable Context context) { + if (context == null) { + return; + } + ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + if (clipboard == null) { + return; + } + + clipboard.setPrimaryClip(ClipData.newPlainText("", "")); + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java index 8ed4c0ea6..666d73599 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpHelper.java @@ -84,22 +84,16 @@ public class PgpHelper { } public static String getPgpMessageContent(@NonNull CharSequence input) { - Timber.d("input: %s"); - Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(input); if (matcher.matches()) { String text = matcher.group(1); text = fixPgpMessage(text); - - Timber.d("input fixed: %s", text); return text; } else { matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(input); if (matcher.matches()) { String text = matcher.group(1); text = fixPgpCleartextSignature(text); - - Timber.d("input fixed: %s", text); return text; } else { return null; @@ -108,8 +102,6 @@ public class PgpHelper { } public static String getPgpPublicKeyContent(@NonNull CharSequence input) { - Timber.d("input: %s", input); - Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(input); if (!matcher.matches()) { return null; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptFragment.java index 5134ca3e3..d0d0cdfcb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptDecryptFragment.java @@ -117,25 +117,23 @@ public class EncryptDecryptFragment extends Fragment { public void onResume() { super.onResume(); - // get text from clipboard - final CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity()); + checkClipboardForEncryptedText(); + } - // if it's null, nothing to do here /o/ - if (clipboardText == null) { - return; - } + private void checkClipboardForEncryptedText() { + CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity()); - new AsyncTask() { + new AsyncTask() { @Override - protected Boolean doInBackground(String... clipboardText) { + protected Boolean doInBackground(Void... voids) { // see if it looks like a pgp thing - Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText[0]); + Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(clipboardText); boolean animate = matcher.matches(); // see if it looks like another pgp thing if (!animate) { - matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText[0]); + matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText); animate = matcher.matches(); } return animate; @@ -150,7 +148,7 @@ public class EncryptDecryptFragment extends Fragment { SubtleAttentionSeeker.tada(mClipboardIcon, 1.5f).start(); } } - }.execute(clipboardText.toString()); + }.execute(); } @Override 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 b8399a96b..a4ef34b6a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -17,6 +17,11 @@ package org.sufficientlysecure.keychain.ui; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + import android.app.Activity; import android.content.Intent; import android.net.Uri; @@ -25,10 +30,11 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; -import android.view.ViewGroup; +import android.text.TextUtils; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.keyimport.FacebookKeyserverClient; import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; @@ -38,19 +44,17 @@ import org.sufficientlysecure.keychain.keyimport.processing.ImportKeysOperationC import org.sufficientlysecure.keychain.keyimport.processing.LoaderState; import org.sufficientlysecure.keychain.operations.ImportOperation; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; +import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.service.ImportKeyringParcel; import org.sufficientlysecure.keychain.ui.base.BaseActivity; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify.Style; import org.sufficientlysecure.keychain.util.ParcelableFileCache; import org.sufficientlysecure.keychain.util.Preferences; import timber.log.Timber; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - public class ImportKeysActivity extends BaseActivity implements ImportKeysListener { public static final String ACTION_IMPORT_KEY = Constants.IMPORT_KEY; @@ -69,6 +73,8 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen + "IMPORT_KEY_FROM_FILE"; public static final String ACTION_SEARCH_KEYSERVER_FROM_URL = Constants.INTENT_PREFIX + "SEARCH_KEYSERVER_FROM_URL"; + public static final String ACTION_IMPORT_KEY_FROM_CLIPBOARD = Constants.INTENT_PREFIX + + "IMPORT_KEY_FROM_CLIPBOARD"; public static final String EXTRA_RESULT = "result"; // only used by ACTION_IMPORT_KEY @@ -257,6 +263,10 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen startListFragment(null, null, null, null); break; } + case ACTION_IMPORT_KEY_FROM_CLIPBOARD: { + startListFragmentFromClipboard(); + break; + } default: { startTopCloudFragment(null, null); startListFragment(null, null, null, null); @@ -265,6 +275,22 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen } } + private void startListFragmentFromClipboard() { + CharSequence clipboardText = ClipboardReflection.getClipboardText(this); + if (TextUtils.isEmpty(clipboardText)) { + Notify.create(this, R.string.error_clipboard_empty, Style.ERROR).show(); + return; + } + + String keyText = PgpHelper.getPgpPublicKeyContent(clipboardText); + if (keyText == null) { + Notify.create(this, R.string.error_clipboard_bad, Style.ERROR).show(); + return; + } + + startListFragment(keyText.getBytes(), null, null, null); + } + /** * Shows the list of keys to be imported. * If the fragment is started with non-null bytes/dataUri/serverQuery, it will immediately @@ -387,6 +413,10 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen setResult(Activity.RESULT_OK, intent); finish(); } else if (result.isOkNew() || result.isOkUpdated()) { + if (ACTION_IMPORT_KEY_FROM_CLIPBOARD.equals(intentAction)) { + ClipboardReflection.clearClipboard(getApplicationContext()); + } + // User has successfully imported a key, hide first time dialog Preferences.getPreferences(this).setFirstTime(false); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 5cd70883c..acfb1759b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -26,6 +26,7 @@ import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; @@ -50,11 +51,13 @@ import com.getbase.floatingactionbutton.FloatingActionsMenu; import com.tonicartos.superslim.LayoutManager; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.operations.results.BenchmarkResult; import org.sufficientlysecure.keychain.operations.results.ImportKeyResult; import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.provider.KeyRepository; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; @@ -66,6 +69,8 @@ import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.base.RecyclerFragment; import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity; import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify.ActionListener; +import org.sufficientlysecure.keychain.ui.util.Notify.Style; import org.sufficientlysecure.keychain.util.FabContainer; import org.sufficientlysecure.keychain.util.Preferences; import timber.log.Timber; @@ -254,6 +259,54 @@ public class KeyListFragment extends RecyclerFragment getLoaderManager().initLoader(0, null, this); } + @Override + public void onStart() { + super.onStart(); + + checkClipboardForPublicKeyMaterial(); + } + + private void checkClipboardForPublicKeyMaterial() { + CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity()); + + new AsyncTask() { + @Override + protected Boolean doInBackground(Void... voids) { + if (clipboardText == null) { + return false; + } + + // see if it looks like a pgp thing + String publicKeyContent = PgpHelper.getPgpPublicKeyContent(clipboardText); + + return publicKeyContent != null; + } + + @Override + protected void onPostExecute(Boolean clipboardDataFound) { + super.onPostExecute(clipboardDataFound); + + if (clipboardDataFound) { + showClipboardDataSnackbar(); + } + } + }.execute(); + } + + private void showClipboardDataSnackbar() { + Activity activity = getActivity(); + if (activity == null) { + return; + } + + Notify.create(activity, R.string.snack_keylist_clipboard_title, Notify.LENGTH_INDEFINITE, Style.OK, + () -> { + Intent intentImportExisting = new Intent(getActivity(), ImportKeysActivity.class); + intentImportExisting.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_CLIPBOARD); + startActivity(intentImportExisting); + }, R.string.snack_keylist_clipboard_action).show(this); + } + private void startSearchForQuery() { Activity activity = getActivity(); if (activity == null) { diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index ce67455ff..25e3f2d99 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -2021,4 +2021,7 @@ Go to OpenKeychain I have written down this backup code. Without it, I will be unable to restore the backup. The server does not support the current query! Some servers only accept mailaddresses. Please redefine or try a different server. + + Found key data in clipboard! + View