mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-11 03:25:05 -05:00
Fix nfc, make edit activity like a modal dialog, move all menu actions into view activity
This commit is contained in:
parent
db25433890
commit
5af4f6b63f
@ -23,10 +23,7 @@ import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.OperationApplicationException;
|
||||
import android.database.Cursor;
|
||||
import android.database.CursorWindow;
|
||||
import android.database.CursorWrapper;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.database.sqlite.SQLiteCursor;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
|
||||
@ -42,8 +39,8 @@ import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
|
||||
import org.sufficientlysecure.keychain.remote.AccountSettings;
|
||||
@ -72,6 +69,7 @@ public class ProviderHelper {
|
||||
public static Object getGenericData(Context context, Uri uri, String column, int type) {
|
||||
return getGenericData(context, uri, new String[] { column }, new int[] { type }).get(column);
|
||||
}
|
||||
|
||||
public static HashMap<String,Object> getGenericData(Context context, Uri uri, String[] proj, int[] types) {
|
||||
Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
|
||||
|
||||
@ -100,11 +98,13 @@ public class ProviderHelper {
|
||||
public static Object getUnifiedData(Context context, long masterKeyId, String column, int type) {
|
||||
return getUnifiedData(context, masterKeyId, new String[] { column }, new int[] { type }).get(column);
|
||||
}
|
||||
|
||||
public static HashMap<String,Object> getUnifiedData(Context context, long masterKeyId, String[] proj, int[] types) {
|
||||
return getGenericData(context, KeyRings.buildUnifiedKeyRingUri(Long.toString(masterKeyId)), proj, types);
|
||||
}
|
||||
|
||||
/** Find the master key id related to a given query. The id will either be extracted from the
|
||||
/**
|
||||
* Find the master key id related to a given query. The id will either be extracted from the
|
||||
* query, which should work for all specific /key_rings/ queries, or will be queried if it can't.
|
||||
*/
|
||||
public static long getMasterKeyId(Context context, Uri queryUri) {
|
||||
@ -333,12 +333,6 @@ public class ProviderHelper {
|
||||
return ContentProviderOperation.newInsert(uri).withValues(values).build();
|
||||
}
|
||||
|
||||
public static boolean hasSecretKeyByMasterKeyId(Context context, long masterKeyId) {
|
||||
Uri queryUri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId));
|
||||
// see if we can get our master key id back from the uri
|
||||
return getMasterKeyId(context, queryUri) == masterKeyId;
|
||||
}
|
||||
|
||||
public static ArrayList<String> getKeyRingsAsArmoredString(Context context, long[] masterKeyIds) {
|
||||
ArrayList<String> output = new ArrayList<String>();
|
||||
|
||||
@ -398,6 +392,7 @@ public class ProviderHelper {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Cursor getCursorWithSelectedKeyringMasterKeyIds(Context context, long[] masterKeyIds) {
|
||||
Cursor cursor = null;
|
||||
if (masterKeyIds != null && masterKeyIds.length > 0) {
|
||||
|
@ -31,8 +31,6 @@ import android.os.Messenger;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
@ -47,22 +45,20 @@ import com.devspark.appmsg.AppMsg;
|
||||
|
||||
import org.spongycastle.openpgp.PGPSecretKey;
|
||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
||||
import org.sufficientlysecure.keychain.helper.ExportHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.widget.Editor;
|
||||
@ -142,9 +138,24 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
|
||||
|
||||
mExportHelper = new ExportHelper(this);
|
||||
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setIcon(android.R.color.transparent);
|
||||
getSupportActionBar().setHomeButtonEnabled(true);
|
||||
// Inflate a "Done"/"Cancel" custom action bar view
|
||||
ActionBarHelper.setTwoButtonView(getSupportActionBar(),
|
||||
R.string.btn_save, R.drawable.ic_action_save,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// Save
|
||||
saveClicked();
|
||||
}
|
||||
}, R.string.menu_key_edit_cancel, R.drawable.ic_action_cancel,
|
||||
new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// Cancel
|
||||
cancelClicked();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
mUserIds = new Vector<String>();
|
||||
mKeys = new Vector<PGPSecretKey>();
|
||||
@ -281,62 +292,6 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.key_edit, menu);
|
||||
//totally get rid of some actions for new keys
|
||||
if (mDataUri == null) {
|
||||
MenuItem mButton = menu.findItem(R.id.menu_key_edit_export_file);
|
||||
mButton.setVisible(false);
|
||||
mButton = menu.findItem(R.id.menu_key_edit_delete);
|
||||
mButton.setVisible(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
cancelClicked();
|
||||
// TODO: why isn't this triggered on my tablet - one of many ui problems
|
||||
// I've had with this device. A code compatibility issue or a Samsung fail?
|
||||
return true;
|
||||
case R.id.menu_key_edit_cancel:
|
||||
cancelClicked();
|
||||
return true;
|
||||
case R.id.menu_key_edit_export_file:
|
||||
if (needsSaving()) {
|
||||
Toast.makeText(this, R.string.error_save_first, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
|
||||
mExportHelper.showExportKeysDialog(
|
||||
new long[] { masterKeyId }, Constants.Path.APP_DIR_FILE_SEC, true);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
case R.id.menu_key_edit_delete:
|
||||
Uri convertUri = KeyRingData.buildSecretKeyRingUri(mDataUri);
|
||||
// Message is received after key is deleted
|
||||
Handler returnHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
}
|
||||
}};
|
||||
mExportHelper.deleteKey(convertUri, returnHandler);
|
||||
return true;
|
||||
|
||||
case R.id.menu_key_edit_save:
|
||||
saveClicked();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void finallyEdit(final long masterKeyId) {
|
||||
if (masterKeyId != 0) {
|
||||
@ -525,16 +480,16 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
|
||||
}
|
||||
if (passphrase == null) {
|
||||
PassphraseDialogFragment.show(this, masterKeyId,
|
||||
new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
|
||||
mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(
|
||||
EditKeyActivity.this, masterKeyId);
|
||||
checkEmptyIDsWanted();
|
||||
new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
if (message.what == PassphraseDialogFragment.MESSAGE_OKAY) {
|
||||
mCurrentPassphrase = PassphraseCacheService.getCachedPassphrase(
|
||||
EditKeyActivity.this, masterKeyId);
|
||||
checkEmptyIDsWanted();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
mCurrentPassphrase = passphrase;
|
||||
checkEmptyIDsWanted();
|
||||
|
@ -31,6 +31,7 @@ import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.Window;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
@ -44,6 +45,7 @@ import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ViewKeyActivity extends ActionBarActivity {
|
||||
|
||||
@ -119,12 +121,7 @@ public class ViewKeyActivity extends ActionBarActivity {
|
||||
uploadToKeyserver(mDataUri);
|
||||
return true;
|
||||
case R.id.menu_key_view_export_file:
|
||||
long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
|
||||
mExportHelper.showExportKeysDialog(
|
||||
new long[] { masterKeyId } , Constants.Path.APP_DIR_FILE_PUB,
|
||||
// TODO this doesn't work?
|
||||
((ViewKeyMainFragment) mTabsAdapter.getItem(0)).isSecretAvailable()
|
||||
);
|
||||
exportToFile(mDataUri);
|
||||
return true;
|
||||
case R.id.menu_key_view_share_default_fingerprint:
|
||||
shareKey(mDataUri, true);
|
||||
@ -152,6 +149,21 @@ public class ViewKeyActivity extends ActionBarActivity {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void exportToFile(Uri dataUri) {
|
||||
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
|
||||
|
||||
HashMap<String, Object> data = ProviderHelper.getGenericData(this,
|
||||
baseUri,
|
||||
new String[]{KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
|
||||
new int[]{ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
|
||||
|
||||
mExportHelper.showExportKeysDialog(
|
||||
new long[]{(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
|
||||
Constants.Path.APP_DIR_FILE_PUB,
|
||||
((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) == 1)
|
||||
);
|
||||
}
|
||||
|
||||
private void uploadToKeyserver(Uri dataUri) {
|
||||
Intent uploadIntent = new Intent(this, UploadKeyActivity.class);
|
||||
uploadIntent.setData(dataUri);
|
||||
@ -177,7 +189,7 @@ public class ViewKeyActivity extends ActionBarActivity {
|
||||
byte[] data = (byte[]) ProviderHelper.getGenericData(
|
||||
this, KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri),
|
||||
KeychainContract.Keys.FINGERPRINT, ProviderHelper.FIELD_TYPE_BLOB);
|
||||
if(data != null) {
|
||||
if (data != null) {
|
||||
String fingerprint = PgpKeyHelper.convertFingerprintToHex(data);
|
||||
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
|
||||
} else {
|
||||
@ -189,7 +201,7 @@ public class ViewKeyActivity extends ActionBarActivity {
|
||||
// get public keyring as ascii armored string
|
||||
long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
|
||||
ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
|
||||
this, new long[]{ masterKeyId });
|
||||
this, new long[]{masterKeyId});
|
||||
|
||||
content = keyringArmored.get(0);
|
||||
|
||||
@ -220,7 +232,7 @@ public class ViewKeyActivity extends ActionBarActivity {
|
||||
// get public keyring as ascii armored string
|
||||
long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
|
||||
ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
|
||||
this, new long[]{ masterKeyId });
|
||||
this, new long[]{masterKeyId});
|
||||
|
||||
ClipboardReflection.copyToClipboard(this, keyringArmored.get(0));
|
||||
Toast.makeText(getApplicationContext(), R.string.key_copied_to_clipboard, Toast.LENGTH_LONG)
|
||||
|
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2013 Bahtiar 'kalkin' Gadimov
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -19,7 +18,6 @@
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NdefMessage;
|
||||
import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter;
|
||||
@ -31,6 +29,9 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.devspark.appmsg.AppMsg;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
@ -42,7 +43,6 @@ import java.io.IOException;
|
||||
public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMessageCallback,
|
||||
OnNdefPushCompleteCallback {
|
||||
|
||||
// NFC
|
||||
private NfcAdapter mNfcAdapter;
|
||||
private byte[] mSharedKeyringBytes;
|
||||
private static final int NFC_SENT = 1;
|
||||
@ -50,6 +50,8 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
initNfc();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -81,17 +83,15 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess
|
||||
* guarantee that this activity starts when receiving a beamed message. For now, this code
|
||||
* uses the tag dispatch system.
|
||||
*/
|
||||
// get public keyring as byte array
|
||||
long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri);
|
||||
try {
|
||||
mSharedKeyringBytes = ProviderHelper.getPGPPublicKeyRing(this, masterKeyId).getEncoded();
|
||||
// get public keyring as byte array
|
||||
mSharedKeyringBytes = ProviderHelper.getPGPKeyRing(this, mDataUri).getEncoded();
|
||||
|
||||
NdefMessage msg = new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
|
||||
mSharedKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
|
||||
return msg;
|
||||
} catch(IOException e) {
|
||||
// not much trouble, but leave a note
|
||||
Log.e(Constants.TAG, "Error parsing keyring: ", e);
|
||||
Log.e(Constants.TAG, "Error parsing keyring", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -114,8 +114,8 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case NFC_SENT:
|
||||
Toast.makeText(getApplicationContext(), R.string.nfc_successfull, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
AppMsg.makeText(ViewKeyActivityJB.this, R.string.nfc_successfull,
|
||||
AppMsg.STYLE_INFO).show();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -81,9 +81,6 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
|
||||
private Uri mDataUri;
|
||||
|
||||
// for activity
|
||||
private boolean mSecretAvailable = false;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.view_key_main_fragment, container, false);
|
||||
@ -231,8 +228,6 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
mComment.setText(mainUserId[2]);
|
||||
|
||||
if (data.getInt(INDEX_UNIFIED_HAS_SECRET) != 0) {
|
||||
mSecretAvailable = true;
|
||||
|
||||
mSecretKey.setTextColor(getResources().getColor(R.color.emphasis));
|
||||
mSecretKey.setText(R.string.secret_key_yes);
|
||||
|
||||
@ -247,8 +242,6 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mSecretAvailable = false;
|
||||
|
||||
mSecretKey.setTextColor(Color.BLACK);
|
||||
mSecretKey.setText(getResources().getString(R.string.secret_key_no));
|
||||
|
||||
@ -337,11 +330,6 @@ public class ViewKeyMainFragment extends Fragment implements
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true if the key current displayed is known to have a secret key. */
|
||||
public boolean isSecretAvailable() {
|
||||
return mSecretAvailable;
|
||||
}
|
||||
|
||||
private void encryptToContact(Uri dataUri) {
|
||||
// TODO preselect from uri? should be feasible without trivial query
|
||||
long keyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri);
|
||||
|
@ -192,8 +192,7 @@
|
||||
<TextView
|
||||
android:id="@+id/secret_key"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:typeface="monospace" />
|
||||
android:layout_height="wrap_content" />
|
||||
</TableRow>
|
||||
</TableLayout>
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_key_edit_save"
|
||||
android:icon="@drawable/ic_action_save"
|
||||
app:showAsAction="always"
|
||||
android:title="@string/btn_save">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/menu_key_edit_export_file"
|
||||
app:showAsAction="never"
|
||||
android:title="@string/menu_export_key" />
|
||||
<item
|
||||
android:id="@+id/menu_key_edit_delete"
|
||||
app:showAsAction="never"
|
||||
android:title="@string/menu_delete_key" />
|
||||
<item
|
||||
android:id="@+id/menu_key_edit_cancel"
|
||||
app:showAsAction="never"
|
||||
android:title="@string/menu_key_edit_cancel" />
|
||||
|
||||
</menu>
|
Loading…
Reference in New Issue
Block a user