more work on streamlining uris, and stripping ProviderHelper

This commit is contained in:
Vincent Breitmoser 2014-04-03 17:09:26 +02:00
parent 428e94bb57
commit dedcfd8a72
10 changed files with 146 additions and 221 deletions

View File

@ -256,6 +256,9 @@ public class KeychainProvider extends ContentProvider {
+ Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC"; + Tables.USER_IDS + "." + UserIdsColumns.USER_ID + " ASC";
} }
// uri to watch is all /key_rings/
uri = KeyRings.CONTENT_URI;
break; break;
} }
/*case SECRET_KEY_RING_BY_EMAILS: /*case SECRET_KEY_RING_BY_EMAILS:
@ -503,6 +506,7 @@ public class KeychainProvider extends ContentProvider {
} }
// corresponding keys and userIds are deleted by ON DELETE CASCADE // corresponding keys and userIds are deleted by ON DELETE CASCADE
count = db.delete(Tables.KEY_RINGS_PUBLIC, selection, selectionArgs); count = db.delete(Tables.KEY_RINGS_PUBLIC, selection, selectionArgs);
uri = KeyRings.buildGenericKeyRingUri(uri.getPathSegments().get(1));
break; break;
} }
case KEY_RING_SECRET: { case KEY_RING_SECRET: {
@ -512,6 +516,7 @@ public class KeychainProvider extends ContentProvider {
selection += " AND (" + additionalSelection + ")"; selection += " AND (" + additionalSelection + ")";
} }
count = db.delete(Tables.KEY_RINGS_SECRET, selection, selectionArgs); count = db.delete(Tables.KEY_RINGS_SECRET, selection, selectionArgs);
uri = KeyRings.buildGenericKeyRingUri(uri.getPathSegments().get(1));
break; break;
} }

View File

@ -23,7 +23,10 @@ import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.OperationApplicationException; import android.content.OperationApplicationException;
import android.database.Cursor; import android.database.Cursor;
import android.database.CursorWindow;
import android.database.CursorWrapper;
import android.database.DatabaseUtils; import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteCursor;
import android.net.Uri; import android.net.Uri;
import android.os.RemoteException; import android.os.RemoteException;
@ -42,7 +45,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys; import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.remote.AppSettings; import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.IterableIterator;
@ -52,6 +54,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -81,6 +84,57 @@ public class ProviderHelper {
return keyRing; return keyRing;
} }
public static Object getUnifiedData(Context context, long masterKeyId, String column) {
return getUnifiedData(context, masterKeyId, new String[] { column }).get(column);
}
public static Object getUnifiedData(Context context, Uri uri, String column) {
return getUnifiedData(context, uri, new String[] { column }).get(column);
}
public static HashMap<String,Object> getUnifiedData(Context context, long masterKeyId, String[] proj) {
return getUnifiedData(context, KeyRings.buildGenericKeyRingUri(Long.toString(masterKeyId)), proj);
}
public static HashMap<String,Object> getUnifiedData(Context context, Uri uri, String[] proj) {
uri = KeyRings.buildUnifiedKeyRingUri(uri);
Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
HashMap<String, Object> result = new HashMap<String, Object>(proj.length);
if (cursor != null && cursor.moveToFirst()) {
// this is a HACK because we don't have Cursor.getType (which is api level 11)
CursorWindow cursorWindow;
if(cursor instanceof CursorWrapper) {
cursorWindow = ((SQLiteCursor) ((CursorWrapper) cursor).getWrappedCursor()).getWindow();
} else {
cursorWindow = ((SQLiteCursor) cursor).getWindow();
}
int pos = 0;
for(String p : proj) {
if (cursorWindow.isNull(0, pos)) {
result.put(p, cursor.isNull(pos));
} else if (cursorWindow.isLong(0, pos)) {
result.put(p, cursor.getLong(pos));
} else if (cursorWindow.isFloat(0, pos)) {
result.put(p, cursor.getFloat(pos));
} else if (cursorWindow.isString(0, pos)) {
result.put(p, cursor.getString(pos));
} else if (cursorWindow.isBlob(0, pos)) {
result.put(p, cursor.getBlob(pos));
}
pos += 1;
}
}
if (cursor != null) {
cursor.close();
}
return result;
}
public static PGPPublicKey getPGPPublicKeyByKeyId(Context context, long keyId) { public static PGPPublicKey getPGPPublicKeyByKeyId(Context context, long keyId) {
return getPGPPublicKeyRingWithKeyId(context, keyId).getPublicKey(keyId); return getPGPPublicKeyRingWithKeyId(context, keyId).getPublicKey(keyId);
} }
@ -307,84 +361,6 @@ public class ProviderHelper {
return masterKeyId; return masterKeyId;
} }
public static long getRowId(Context context, Uri queryUri) {
String[] projection = new String[]{KeyRings._ID};
Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null);
long rowId = 0;
try {
if (cursor != null && cursor.moveToFirst()) {
int idCol = cursor.getColumnIndexOrThrow(KeyRings._ID);
rowId = cursor.getLong(idCol);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
return rowId;
}
/**
* Get fingerprint of key
*/
public static byte[] getFingerprint(Context context, Uri queryUri) {
String[] projection = new String[]{Keys.FINGERPRINT};
Cursor cursor = context.getContentResolver().query(queryUri, projection, null, null, null);
byte[] fingerprint = null;
try {
if (cursor != null && cursor.moveToFirst()) {
int col = cursor.getColumnIndexOrThrow(Keys.FINGERPRINT);
fingerprint = cursor.getBlob(col);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
// FALLBACK: If fingerprint is not in database, get it from key blob!
// this could happen if the key was saved by a previous version of Keychain!
if (fingerprint == null) {
Log.d(Constants.TAG, "FALLBACK: fingerprint is not in database, get it from key blob!");
// get master key id
projection = new String[]{KeyRings.MASTER_KEY_ID};
cursor = context.getContentResolver().query(queryUri, projection, null, null, null);
long masterKeyId = 0;
try {
if (cursor != null && cursor.moveToFirst()) {
int col = cursor.getColumnIndexOrThrow(KeyRings.MASTER_KEY_ID);
masterKeyId = cursor.getLong(col);
}
} finally {
if (cursor != null) {
cursor.close();
}
}
PGPPublicKey key = ProviderHelper.getPGPPublicKeyRing(context, masterKeyId).getPublicKey();
// if it is no public key get it from your own keys...
if (key == null) {
PGPSecretKey secretKey = ProviderHelper.getPGPSecretKeyRing(context, masterKeyId).getSecretKey();
if (secretKey == null) {
Log.e(Constants.TAG, "Key could not be found!");
return null;
}
key = secretKey.getPublicKey();
}
fingerprint = key.getFingerprint();
}
return fingerprint;
}
public static ArrayList<String> getKeyRingsAsArmoredString(Context context, Uri uri, public static ArrayList<String> getKeyRingsAsArmoredString(Context context, Uri uri,
long[] masterKeyIds) { long[] masterKeyIds) {
ArrayList<String> output = new ArrayList<String>(); ArrayList<String> output = new ArrayList<String>();

View File

@ -34,6 +34,7 @@ import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AccountSettings; import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.ui.EditKeyActivity; import org.sufficientlysecure.keychain.ui.EditKeyActivity;
import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment; import org.sufficientlysecure.keychain.ui.SelectSecretKeyLayoutFragment;
@ -176,9 +177,8 @@ public class AccountSettingsFragment extends Fragment implements
case REQUEST_CODE_CREATE_KEY: { case REQUEST_CODE_CREATE_KEY: {
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
// select newly created key // select newly created key
Uri newKeyUri = data.getData(); long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), data.getData());
// TODO helper method for this? mSelectKeyFragment.selectKey(masterKeyId);
mSelectKeyFragment.selectKey(Long.parseLong(newKeyUri.getPathSegments().get(1)));
} }
break; break;
} }

View File

@ -37,8 +37,10 @@ import org.spongycastle.openpgp.PGPSecretKeyRing;
import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import java.util.HashMap;
import java.util.Vector; import java.util.Vector;
public class EncryptAsymmetricFragment extends Fragment { public class EncryptAsymmetricFragment extends Fragment {
@ -202,20 +204,17 @@ public class EncryptAsymmetricFragment extends Fragment {
} else { } else {
String uid = getResources().getString(R.string.user_id_no_name); String uid = getResources().getString(R.string.user_id_no_name);
String uidExtra = ""; String uidExtra = "";
// TODO: don't use bouncy castle objects! // See if we can get a user_id from a unified query
PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingWithKeyId(getActivity(), Object data = ProviderHelper.getUnifiedData(
mSecretKeyId); getActivity(), mSecretKeyId, KeychainContract.UserIds.USER_ID);
if (keyRing != null) { if(data instanceof String) {
PGPSecretKey key = PgpKeyHelper.getMasterKey(keyRing); String chunks[] = ((String) data).split(" <", 2);
if (key != null) { uid = chunks[0];
String userId = PgpKeyHelper.getMainUserIdSafe(getActivity(), key); if (chunks.length > 1) {
String chunks[] = userId.split(" <", 2); uidExtra = "<" + chunks[1];
uid = chunks[0];
if (chunks.length > 1) {
uidExtra = "<" + chunks[1];
}
} }
} }
mMainUserId.setText(uid); mMainUserId.setText(uid);
mMainUserIdRest.setText(uidExtra); mMainUserIdRest.setText(uidExtra);
mSign.setChecked(true); mSign.setChecked(true);

View File

@ -193,28 +193,15 @@ public class KeyListFragment extends Fragment
break; break;
} }
case R.id.menu_key_list_multi_delete: { case R.id.menu_key_list_multi_delete: {
ids = mStickyList.getWrappedList().getCheckedItemIds(); ids = mAdapter.getCurrentSelectedMasterKeyIds();
showDeleteKeyDialog(mode, ids); showDeleteKeyDialog(mode, ids);
break; break;
} }
case R.id.menu_key_list_multi_export: { case R.id.menu_key_list_multi_export: {
ids = mStickyList.getWrappedList().getCheckedItemIds(); ids = mAdapter.getCurrentSelectedMasterKeyIds();
long[] masterKeyIds = new long[2*ids.length];
/* TODO! redo
ArrayList<Long> allPubRowIds =
ProviderHelper.getPublicKeyRingsRowIds(getActivity());
for (int i = 0; i < ids.length; i++) {
if (allPubRowIds.contains(ids[i])) {
masterKeyIds[i] =
ProviderHelper.getPublicMasterKeyId(getActivity(), ids[i]);
} else {
masterKeyIds[i] =
ProviderHelper.getSecretMasterKeyId(getActivity(), ids[i]);
}
}*/
ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity()); ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity());
mExportHelper mExportHelper
.showExportKeysDialog(masterKeyIds, Id.type.public_key, .showExportKeysDialog(ids, Id.type.public_key,
Constants.Path.APP_DIR_FILE_PUB, Constants.Path.APP_DIR_FILE_PUB,
getString(R.string.also_export_secret_keys)); getString(R.string.also_export_secret_keys));
break; break;
@ -343,7 +330,7 @@ public class KeyListFragment extends Fragment
} }
viewIntent.setData( viewIntent.setData(
KeychainContract KeychainContract
.KeyRings.buildPublicKeyRingUri( .KeyRings.buildGenericKeyRingUri(
Long.toString(mAdapter.getMasterKeyId(position)))); Long.toString(mAdapter.getMasterKeyId(position))));
startActivity(viewIntent); startActivity(viewIntent);
} }
@ -362,11 +349,11 @@ public class KeyListFragment extends Fragment
/** /**
* Show dialog to delete key * Show dialog to delete key
* *
* @param keyRingRowIds * @param masterKeyIds
*/ */
@TargetApi(11) @TargetApi(11)
// TODO: this method needs an overhaul to handle both public and secret keys gracefully! // TODO: this method needs an overhaul to handle both public and secret keys gracefully!
public void showDeleteKeyDialog(final ActionMode mode, long[] keyRingRowIds) { public void showDeleteKeyDialog(final ActionMode mode, long[] masterKeyIds) {
// Message is received after key is deleted // Message is received after key is deleted
Handler returnHandler = new Handler() { Handler returnHandler = new Handler() {
@Override @Override
@ -381,7 +368,7 @@ public class KeyListFragment extends Fragment
Messenger messenger = new Messenger(returnHandler); Messenger messenger = new Messenger(returnHandler);
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
keyRingRowIds); masterKeyIds);
deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog"); deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog");
} }

View File

@ -173,10 +173,15 @@ public class ViewKeyActivity extends ActionBarActivity {
private void shareKey(Uri dataUri, boolean fingerprintOnly) { private void shareKey(Uri dataUri, boolean fingerprintOnly) {
String content; String content;
if (fingerprintOnly) { if (fingerprintOnly) {
byte[] fingerprintBlob = ProviderHelper.getFingerprint(this, dataUri); Object blob = ProviderHelper.getUnifiedData(this, dataUri, KeychainContract.Keys.FINGERPRINT);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob); if(blob instanceof byte[]) {
String fingerprint = PgpKeyHelper.convertFingerprintToHex((byte[]) blob);
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
} else {
Toast.makeText(getApplicationContext(), "Bad key selected!",
Toast.LENGTH_LONG).show();
return;
}
} else { } else {
// get public keyring as ascii armored string // get public keyring as ascii armored string
long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);

View File

@ -34,6 +34,9 @@ import android.widget.Toast;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log;
import java.io.IOException;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN) @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMessageCallback, public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMessageCallback,
@ -64,13 +67,17 @@ public class ViewKeyActivityJB extends ViewKeyActivity implements CreateNdefMess
// get public keyring as byte array // get public keyring as byte array
long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri); long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
mSharedKeyringBytes = ProviderHelper.getKeyRingsAsByteArray(this, dataUri, try {
new long[]{masterKeyId}); mSharedKeyringBytes = ProviderHelper.getPGPPublicKeyRing(this, masterKeyId).getEncoded();
// Register callback to set NDEF message // Register callback to set NDEF message
mNfcAdapter.setNdefPushMessageCallback(this, this); mNfcAdapter.setNdefPushMessageCallback(this, this);
// Register callback to listen for message-sent success // Register callback to listen for message-sent success
mNfcAdapter.setOnNdefPushCompleteCallback(this, this); mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
} catch(IOException e) {
// not much trouble, but leave a note
Log.e(Constants.TAG, "Error parsing keyring: ", e);
}
} }
} }
} }

View File

@ -298,10 +298,6 @@ public class ViewKeyMainFragment extends Fragment implements
mAlgorithm.setText(algorithmStr); mAlgorithm.setText(algorithmStr);
byte[] fingerprintBlob = data.getBlob(KEYS_INDEX_FINGERPRINT); byte[] fingerprintBlob = data.getBlob(KEYS_INDEX_FINGERPRINT);
if (fingerprintBlob == null) {
// FALLBACK for old database entries
fingerprintBlob = ProviderHelper.getFingerprint(getActivity(), mDataUri);
}
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob); String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob);
mFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint)); mFingerprint.setText(PgpKeyHelper.colorizeFingerprint(fingerprint));

View File

@ -43,10 +43,11 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
public class DeleteKeyDialogFragment extends DialogFragment { public class DeleteKeyDialogFragment extends DialogFragment {
private static final String ARG_MESSENGER = "messenger"; private static final String ARG_MESSENGER = "messenger";
private static final String ARG_DELETE_KEY_RING_ROW_IDS = "delete_key_ring_row_ids"; private static final String ARG_DELETE_MASTER_KEY_IDS = "delete_master_key_ids";
public static final int MESSAGE_OKAY = 1; public static final int MESSAGE_OKAY = 1;
public static final int MESSAGE_ERROR = 0; public static final int MESSAGE_ERROR = 0;
@ -63,13 +64,13 @@ public class DeleteKeyDialogFragment extends DialogFragment {
/** /**
* Creates new instance of this delete file dialog fragment * Creates new instance of this delete file dialog fragment
*/ */
public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] keyRingRowIds public static DeleteKeyDialogFragment newInstance(Messenger messenger,
) { long[] masterKeyIds) {
DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putParcelable(ARG_MESSENGER, messenger); args.putParcelable(ARG_MESSENGER, messenger);
args.putLongArray(ARG_DELETE_KEY_RING_ROW_IDS, keyRingRowIds); args.putLongArray(ARG_DELETE_MASTER_KEY_IDS, masterKeyIds);
//We don't need the key type //We don't need the key type
frag.setArguments(args); frag.setArguments(args);
@ -84,7 +85,7 @@ public class DeleteKeyDialogFragment extends DialogFragment {
final FragmentActivity activity = getActivity(); final FragmentActivity activity = getActivity();
mMessenger = getArguments().getParcelable(ARG_MESSENGER); mMessenger = getArguments().getParcelable(ARG_MESSENGER);
final long[] keyRingRowIds = getArguments().getLongArray(ARG_DELETE_KEY_RING_ROW_IDS); final long[] masterKeyIds = getArguments().getLongArray(ARG_DELETE_MASTER_KEY_IDS);
AlertDialog.Builder builder = new AlertDialog.Builder(activity); AlertDialog.Builder builder = new AlertDialog.Builder(activity);
@ -98,35 +99,29 @@ public class DeleteKeyDialogFragment extends DialogFragment {
mCheckDeleteSecret = (CheckBox) mInflateView.findViewById(R.id.checkDeleteSecret); mCheckDeleteSecret = (CheckBox) mInflateView.findViewById(R.id.checkDeleteSecret);
builder.setTitle(R.string.warning); builder.setTitle(R.string.warning);
/* TODO! redo
//If only a single key has been selected // If only a single key has been selected
if (keyRingRowIds.length == 1) { if (masterKeyIds.length == 1) {
Uri dataUri;
ArrayList<Long> publicKeyRings; //Any one will do
mIsSingleSelection = true; mIsSingleSelection = true;
long selectedRow = keyRingRowIds[0]; long masterKeyId = masterKeyIds[0];
long keyType;
publicKeyRings = ProviderHelper.getPublicKeyRingsRowIds(activity);
if (publicKeyRings.contains(selectedRow)) { HashMap<String, Object> data = ProviderHelper.getUnifiedData(activity, masterKeyId, new String[]{
//TODO Should be a better method to do this other than getting all the KeyRings KeychainContract.UserIds.USER_ID,
dataUri = KeychainContract.KeyRings.buildPublicKeyRingsUri(String.valueOf(selectedRow)); KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID
keyType = Id.type.public_key; });
} else { String userId = (String) data.get(KeychainContract.UserIds.USER_ID);
dataUri = KeychainContract.KeyRings.buildSecretKeyRingsUri(String.valueOf(selectedRow)); boolean hasSecret = data.get(
keyType = Id.type.secret_key; KeychainDatabase.Tables.KEY_RINGS_SECRET + "." + KeychainContract.KeyRings.MASTER_KEY_ID
} ) instanceof Long;
String userId = ProviderHelper.getUserId(activity, dataUri); // Hide the Checkbox and TextView since this is a single selection,user will be notified through message
// Hide the Checkbox and TextView since this is a single selection,
// user will be notified thru message
mDeleteSecretKeyView.setVisibility(View.GONE); mDeleteSecretKeyView.setVisibility(View.GONE);
// Set message depending on which key it is. // Set message depending on which key it is.
mMainMessage.setText(getString(keyType == Id.type.secret_key ? mMainMessage.setText(getString(
R.string.secret_key_deletion_confirmation : hasSecret ? R.string.secret_key_deletion_confirmation
R.string.public_key_deletetion_confirmation, userId)); : R.string.public_key_deletetion_confirmation,
userId));
} else { } else {
mDeleteSecretKeyView.setVisibility(View.VISIBLE); mDeleteSecretKeyView.setVisibility(View.VISIBLE);
mMainMessage.setText(R.string.key_deletion_confirmation_multi); mMainMessage.setText(R.string.key_deletion_confirmation_multi);
@ -137,75 +132,27 @@ public class DeleteKeyDialogFragment extends DialogFragment {
builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
Uri queryUri = KeychainContract.KeyRings.buildUnifiedKeyRingsUri();
String[] projection = new String[]{
KeychainContract.KeyRings.MASTER_KEY_ID, // 0
KeychainContract.KeyRings.TYPE// 1
};
// make selection with all entries where _ID is one of the given row ids boolean success = false;
String selection = KeychainDatabase.Tables.KEY_RINGS + "." + for(long masterKeyId : masterKeyIds) {
KeychainContract.KeyRings._ID + " IN("; int count = activity.getContentResolver().delete(
String selectionIDs = ""; KeychainContract.KeyRings.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null
for (int i = 0; i < keyRingRowIds.length; i++) { );
selectionIDs += "'" + String.valueOf(keyRingRowIds[i]) + "'"; if(count > 0)
if (i + 1 < keyRingRowIds.length) { success = true;
selectionIDs += ",";
}
}
selection += selectionIDs + ")";
Cursor cursor = activity.getContentResolver().query(queryUri, projection,
selection, null, null);
long masterKeyId;
long keyType;
boolean isSuccessfullyDeleted;
try {
isSuccessfullyDeleted = false;
while (cursor != null && cursor.moveToNext()) {
masterKeyId = cursor.getLong(0);
keyType = cursor.getLong(1);
Log.d(Constants.TAG, "masterKeyId: " + masterKeyId +
", keyType:" +
(keyType == KeychainContract.KeyTypes.PUBLIC ?
"Public" : "Private"));
if (keyType == KeychainContract.KeyTypes.SECRET) {
if (mCheckDeleteSecret.isChecked() || mIsSingleSelection) {
ProviderHelper.deleteUnifiedKeyRing(activity,
String.valueOf(masterKeyId), true);
}
} else {
ProviderHelper.deleteUnifiedKeyRing(activity,
String.valueOf(masterKeyId), false);
}
}
//Check if the selected rows have actually been deleted
cursor = activity.getContentResolver().query(
queryUri, projection, selection, null, null);
if (cursor == null || cursor.getCount() == 0 ||
!mCheckDeleteSecret.isChecked()) {
isSuccessfullyDeleted = true;
}
} finally {
if (cursor != null) {
cursor.close();
}
} }
dismiss(); dismiss();
if (isSuccessfullyDeleted) { if (success) {
sendMessageToHandler(MESSAGE_OKAY, null); sendMessageToHandler(MESSAGE_OKAY, null);
} else { } else {
sendMessageToHandler(MESSAGE_ERROR, null); sendMessageToHandler(MESSAGE_ERROR, null);
} }
} }
});
}
);
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override @Override
@ -213,7 +160,7 @@ public class DeleteKeyDialogFragment extends DialogFragment {
dismiss(); dismiss();
} }
}); });
*/
return builder.create(); return builder.create();
} }

View File

@ -31,6 +31,7 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.util.QrCodeUtils; import org.sufficientlysecure.keychain.util.QrCodeUtils;
@ -89,22 +90,24 @@ public class ShareQrCodeDialogFragment extends DialogFragment {
if (mFingerprintOnly) { if (mFingerprintOnly) {
alert.setPositiveButton(R.string.btn_okay, null); alert.setPositiveButton(R.string.btn_okay, null);
byte[] fingerprintBlob = ProviderHelper.getFingerprint(getActivity(), dataUri); Object blob = ProviderHelper.getUnifiedData(getActivity(), dataUri, KeychainContract.Keys.FINGERPRINT);
String fingerprint = PgpKeyHelper.convertFingerprintToHex(fingerprintBlob); if(!(blob instanceof byte[])) {
// TODO error handling?!
return null;
}
String fingerprint = PgpKeyHelper.convertFingerprintToHex((byte[]) blob);
mText.setText(getString(R.string.share_qr_code_dialog_fingerprint_text) + " " + fingerprint); mText.setText(getString(R.string.share_qr_code_dialog_fingerprint_text) + " " + fingerprint);
content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint; content = Constants.FINGERPRINT_SCHEME + ":" + fingerprint;
setQrCode(content); setQrCode(content);
} else { } else {
mText.setText(R.string.share_qr_code_dialog_start); mText.setText(R.string.share_qr_code_dialog_start);
// TODO // TODO works, but
long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri); long masterKeyId = ProviderHelper.getMasterKeyId(getActivity(), dataUri);
// get public keyring as ascii armored string // get public keyring as ascii armored string
ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString( ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(
getActivity(), dataUri, new long[]{masterKeyId}); getActivity(), dataUri, new long[] { masterKeyId });
// TODO: binary? // TODO: binary?