show Snackbar if clipboard contains key data
This commit is contained in:
committed by
Dominik Schürmann
parent
700e06dcb9
commit
89aa99a13f
@@ -34,6 +34,9 @@ public class ClipboardReflection {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
|
if (clipboard == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
ClipData clip = clipboard.getPrimaryClip();
|
ClipData clip = clipboard.getPrimaryClip();
|
||||||
if (clip == null || clip.getItemCount() == 0) {
|
if (clip == null || clip.getItemCount() == 0) {
|
||||||
@@ -48,4 +51,16 @@ public class ClipboardReflection {
|
|||||||
}
|
}
|
||||||
return null;
|
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("", ""));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,22 +84,16 @@ public class PgpHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getPgpMessageContent(@NonNull CharSequence input) {
|
public static String getPgpMessageContent(@NonNull CharSequence input) {
|
||||||
Timber.d("input: %s");
|
|
||||||
|
|
||||||
Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(input);
|
Matcher matcher = PgpHelper.PGP_MESSAGE.matcher(input);
|
||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
String text = matcher.group(1);
|
String text = matcher.group(1);
|
||||||
text = fixPgpMessage(text);
|
text = fixPgpMessage(text);
|
||||||
|
|
||||||
Timber.d("input fixed: %s", text);
|
|
||||||
return text;
|
return text;
|
||||||
} else {
|
} else {
|
||||||
matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(input);
|
matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(input);
|
||||||
if (matcher.matches()) {
|
if (matcher.matches()) {
|
||||||
String text = matcher.group(1);
|
String text = matcher.group(1);
|
||||||
text = fixPgpCleartextSignature(text);
|
text = fixPgpCleartextSignature(text);
|
||||||
|
|
||||||
Timber.d("input fixed: %s", text);
|
|
||||||
return text;
|
return text;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@@ -108,8 +102,6 @@ public class PgpHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static String getPgpPublicKeyContent(@NonNull CharSequence input) {
|
public static String getPgpPublicKeyContent(@NonNull CharSequence input) {
|
||||||
Timber.d("input: %s", input);
|
|
||||||
|
|
||||||
Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(input);
|
Matcher matcher = PgpHelper.PGP_PUBLIC_KEY.matcher(input);
|
||||||
if (!matcher.matches()) {
|
if (!matcher.matches()) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -117,25 +117,23 @@ public class EncryptDecryptFragment extends Fragment {
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
|
||||||
// get text from clipboard
|
checkClipboardForEncryptedText();
|
||||||
final CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
|
}
|
||||||
|
|
||||||
// if it's null, nothing to do here /o/
|
private void checkClipboardForEncryptedText() {
|
||||||
if (clipboardText == null) {
|
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new AsyncTask<String, Void, Boolean>() {
|
new AsyncTask<Void, Void, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
protected Boolean doInBackground(String... clipboardText) {
|
protected Boolean doInBackground(Void... voids) {
|
||||||
|
|
||||||
// see if it looks like a pgp thing
|
// 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();
|
boolean animate = matcher.matches();
|
||||||
|
|
||||||
// see if it looks like another pgp thing
|
// see if it looks like another pgp thing
|
||||||
if (!animate) {
|
if (!animate) {
|
||||||
matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText[0]);
|
matcher = PgpHelper.PGP_CLEARTEXT_SIGNATURE.matcher(clipboardText);
|
||||||
animate = matcher.matches();
|
animate = matcher.matches();
|
||||||
}
|
}
|
||||||
return animate;
|
return animate;
|
||||||
@@ -150,7 +148,7 @@ public class EncryptDecryptFragment extends Fragment {
|
|||||||
SubtleAttentionSeeker.tada(mClipboardIcon, 1.5f).start();
|
SubtleAttentionSeeker.tada(mClipboardIcon, 1.5f).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.execute(clipboardText.toString());
|
}.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -17,6 +17,11 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.ui;
|
package org.sufficientlysecure.keychain.ui;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@@ -25,10 +30,11 @@ import android.os.Bundle;
|
|||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.app.FragmentManager;
|
import android.support.v4.app.FragmentManager;
|
||||||
import android.view.ViewGroup;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
||||||
import org.sufficientlysecure.keychain.keyimport.FacebookKeyserverClient;
|
import org.sufficientlysecure.keychain.keyimport.FacebookKeyserverClient;
|
||||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
||||||
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
|
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.keyimport.processing.LoaderState;
|
||||||
import org.sufficientlysecure.keychain.operations.ImportOperation;
|
import org.sufficientlysecure.keychain.operations.ImportOperation;
|
||||||
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
|
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
|
||||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
|
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
|
||||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
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.ParcelableFileCache;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class ImportKeysActivity extends BaseActivity implements ImportKeysListener {
|
public class ImportKeysActivity extends BaseActivity implements ImportKeysListener {
|
||||||
|
|
||||||
public static final String ACTION_IMPORT_KEY = Constants.IMPORT_KEY;
|
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";
|
+ "IMPORT_KEY_FROM_FILE";
|
||||||
public static final String ACTION_SEARCH_KEYSERVER_FROM_URL = Constants.INTENT_PREFIX
|
public static final String ACTION_SEARCH_KEYSERVER_FROM_URL = Constants.INTENT_PREFIX
|
||||||
+ "SEARCH_KEYSERVER_FROM_URL";
|
+ "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";
|
public static final String EXTRA_RESULT = "result";
|
||||||
|
|
||||||
// only used by ACTION_IMPORT_KEY
|
// only used by ACTION_IMPORT_KEY
|
||||||
@@ -257,6 +263,10 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
|
|||||||
startListFragment(null, null, null, null);
|
startListFragment(null, null, null, null);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ACTION_IMPORT_KEY_FROM_CLIPBOARD: {
|
||||||
|
startListFragmentFromClipboard();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
startTopCloudFragment(null, null);
|
startTopCloudFragment(null, null);
|
||||||
startListFragment(null, null, 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.
|
* Shows the list of keys to be imported.
|
||||||
* If the fragment is started with non-null bytes/dataUri/serverQuery, it will immediately
|
* 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);
|
setResult(Activity.RESULT_OK, intent);
|
||||||
finish();
|
finish();
|
||||||
} else if (result.isOkNew() || result.isOkUpdated()) {
|
} 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
|
// User has successfully imported a key, hide first time dialog
|
||||||
Preferences.getPreferences(this).setFirstTime(false);
|
Preferences.getPreferences(this).setFirstTime(false);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.app.Activity;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.AsyncTask;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.app.LoaderManager;
|
import android.support.v4.app.LoaderManager;
|
||||||
@@ -50,11 +51,13 @@ import com.getbase.floatingactionbutton.FloatingActionsMenu;
|
|||||||
import com.tonicartos.superslim.LayoutManager;
|
import com.tonicartos.superslim.LayoutManager;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
|
||||||
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
import org.sufficientlysecure.keychain.keyimport.HkpKeyserverAddress;
|
||||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||||
import org.sufficientlysecure.keychain.operations.results.BenchmarkResult;
|
import org.sufficientlysecure.keychain.operations.results.BenchmarkResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||||
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
import org.sufficientlysecure.keychain.provider.KeyRepository;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
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.base.RecyclerFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
|
import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
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.FabContainer;
|
||||||
import org.sufficientlysecure.keychain.util.Preferences;
|
import org.sufficientlysecure.keychain.util.Preferences;
|
||||||
import timber.log.Timber;
|
import timber.log.Timber;
|
||||||
@@ -254,6 +259,54 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
|||||||
getLoaderManager().initLoader(0, null, this);
|
getLoaderManager().initLoader(0, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
|
||||||
|
checkClipboardForPublicKeyMaterial();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkClipboardForPublicKeyMaterial() {
|
||||||
|
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
|
||||||
|
|
||||||
|
new AsyncTask<Void, Void, Boolean>() {
|
||||||
|
@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() {
|
private void startSearchForQuery() {
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if (activity == null) {
|
if (activity == null) {
|
||||||
|
|||||||
@@ -2021,4 +2021,7 @@
|
|||||||
<string name="button_goto_openkeychain">Go to OpenKeychain</string>
|
<string name="button_goto_openkeychain">Go to OpenKeychain</string>
|
||||||
<string name="backup_code_checkbox">I have written down this backup code. Without it, I will be unable to restore the backup.</string>
|
<string name="backup_code_checkbox">I have written down this backup code. Without it, I will be unable to restore the backup.</string>
|
||||||
<string name="msg_get_query_not_implemented">The server does not support the current query! Some servers only accept mailaddresses. Please redefine or try a different server.</string>
|
<string name="msg_get_query_not_implemented">The server does not support the current query! Some servers only accept mailaddresses. Please redefine or try a different server.</string>
|
||||||
|
|
||||||
|
<string name="snack_keylist_clipboard_title">Found key data in clipboard!</string>
|
||||||
|
<string name="snack_keylist_clipboard_action">View</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user