From 2816461283c0067f524d94ddf9702e119025c9d3 Mon Sep 17 00:00:00 2001 From: Nikhil Peter Raj Date: Fri, 21 Mar 2014 01:50:20 +0530 Subject: Fix for #410 --- .../keychain/helper/ExportHelper.java | 4 +- .../keychain/provider/ProviderHelper.java | 23 ++- .../keychain/ui/EditKeyActivity.java | 14 +- .../keychain/ui/KeyListFragment.java | 22 +-- .../keychain/ui/ViewKeyActivity.java | 19 +- .../ui/dialog/DeleteKeyDialogFragment.java | 207 ++++++++++++--------- 6 files changed, 147 insertions(+), 142 deletions(-) (limited to 'OpenPGP-Keychain/src/main/java') diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java index 03cf936ee..2bfa796c7 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/helper/ExportHelper.java @@ -53,14 +53,14 @@ public class ExportHelper { this.mActivity = activity; } - public void deleteKey(Uri dataUri, final int keyType, Handler deleteHandler) { + public void deleteKey(Uri dataUri, Handler deleteHandler) { long keyRingRowId = Long.valueOf(dataUri.getLastPathSegment()); // Create a new Messenger for the communication back Messenger messenger = new Messenger(deleteHandler); DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, - new long[]{keyRingRowId}, keyType); + new long[]{keyRingRowId}); deleteKeyDialog.show(mActivity.getSupportFragmentManager(), "deleteKeyDialog"); } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index db2c57207..8b6feeafd 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Dominik Schürmann + * Copyright (C) 2012-2013 Dominik Schürmann * * 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 @@ -230,7 +230,7 @@ public class ProviderHelper { // get current _ID of key long currentRowId = -1; Cursor oldQuery = context.getContentResolver() - .query(deleteUri, new String[]{KeyRings._ID}, null, null, null); + .query(deleteUri, new String[]{KeyRings._ID}, null, null, null); if (oldQuery != null && oldQuery.moveToFirst()) { currentRowId = oldQuery.getLong(0); } else { @@ -288,7 +288,7 @@ public class ProviderHelper { * Build ContentProviderOperation to add PGPPublicKey to database corresponding to a keyRing */ private static ContentProviderOperation buildPublicKeyOperations(Context context, - long keyRingRowId, PGPPublicKey key, int rank) throws IOException { + long keyRingRowId, PGPPublicKey key, int rank) throws IOException { ContentValues values = new ContentValues(); values.put(Keys.KEY_ID, key.getKeyID()); values.put(Keys.IS_MASTER_KEY, key.isMasterKey()); @@ -316,7 +316,7 @@ public class ProviderHelper { * Build ContentProviderOperation to add PublicUserIds to database corresponding to a keyRing */ private static ContentProviderOperation buildPublicUserIdOperations(Context context, - long keyRingRowId, String userId, int rank) { + long keyRingRowId, String userId, int rank) { ContentValues values = new ContentValues(); values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId); values.put(UserIds.USER_ID, userId); @@ -331,7 +331,7 @@ public class ProviderHelper { * Build ContentProviderOperation to add PGPSecretKey to database corresponding to a keyRing */ private static ContentProviderOperation buildSecretKeyOperations(Context context, - long keyRingRowId, PGPSecretKey key, int rank) throws IOException { + long keyRingRowId, PGPSecretKey key, int rank) throws IOException { ContentValues values = new ContentValues(); boolean hasPrivate = true; @@ -368,7 +368,7 @@ public class ProviderHelper { * Build ContentProviderOperation to add SecretUserIds to database corresponding to a keyRing */ private static ContentProviderOperation buildSecretUserIdOperations(Context context, - long keyRingRowId, String userId, int rank) { + long keyRingRowId, String userId, int rank) { ContentValues values = new ContentValues(); values.put(UserIds.KEY_RING_ROW_ID, keyRingRowId); values.put(UserIds.USER_ID, userId); @@ -469,6 +469,15 @@ public class ProviderHelper { cr.delete(KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)), null, null); } + public static void deleteUnifiedKeyRing(Context context,String masterKeyId,boolean isSecretKey){ + ContentResolver cr= context.getContentResolver(); + cr.delete(KeyRings.buildPublicKeyRingsByMasterKeyIdUri(masterKeyId),null,null); + if(isSecretKey){ + cr.delete(KeyRings.buildSecretKeyRingsByMasterKeyIdUri(masterKeyId),null,null); + } + + } + /** * Get master key id of keyring by its row id */ @@ -855,4 +864,4 @@ public class ProviderHelper { return signature; } -} +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java index 31804719f..654942db7 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivity.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Dominik Schürmann + * Copyright (C) 2012-2013 Dominik Schürmann * Copyright (C) 2010 Thialfihar * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -46,6 +46,7 @@ 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.service.KeychainIntentService; import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler; @@ -58,7 +59,6 @@ import org.sufficientlysecure.keychain.ui.widget.SectionView; import org.sufficientlysecure.keychain.ui.widget.UserIdEditor; import org.sufficientlysecure.keychain.util.IterableIterator; import org.sufficientlysecure.keychain.util.Log; - import java.util.ArrayList; import java.util.GregorianCalendar; import java.util.Vector; @@ -325,9 +325,13 @@ public class EditKeyActivity extends ActionBarActivity { long masterKeyId = ProviderHelper.getMasterKeyId(this, mDataUri); long[] ids = new long[]{masterKeyId}; mExportHelper.showExportKeysDialog(ids, Id.type.secret_key, Constants.Path.APP_DIR_FILE_SEC, - null); + null); return true; case R.id.menu_key_edit_delete: { + //Convert the uri to one based on rowId + long rowId= ProviderHelper.getRowId(this,mDataUri); + Uri convertUri = KeychainContract.KeyRings.buildSecretKeyRingsUri(Long.toString(rowId)); + // Message is received after key is deleted Handler returnHandler = new Handler() { @Override @@ -339,7 +343,7 @@ public class EditKeyActivity extends ActionBarActivity { } }; - mExportHelper.deleteKey(mDataUri, Id.type.secret_key, returnHandler); + mExportHelper.deleteKey(convertUri, returnHandler); return true; } } @@ -697,4 +701,4 @@ public class EditKeyActivity extends ActionBarActivity { : getString(R.string.btn_set_passphrase)); } -} +} \ No newline at end of file diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index cac8b7046..daf455c03 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -355,25 +355,7 @@ public class KeyListFragment extends Fragment @Override public void handleMessage(Message message) { if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) { - Bundle returnData = message.getData(); - if (returnData != null - && returnData.containsKey(DeleteKeyDialogFragment.MESSAGE_NOT_DELETED)) { - ArrayList notDeleted = - returnData.getStringArrayList(DeleteKeyDialogFragment.MESSAGE_NOT_DELETED); - String notDeletedMsg = ""; - for (String userId : notDeleted) { - notDeletedMsg += userId + "\n"; - } - Toast.makeText(getActivity(), - getString(R.string.error_can_not_delete_contacts, notDeletedMsg) - + getResources() - .getQuantityString( - R.plurals.error_can_not_delete_info, - notDeleted.size()), - Toast.LENGTH_LONG).show(); - - mode.finish(); - } + mode.finish(); } } }; @@ -382,7 +364,7 @@ public class KeyListFragment extends Fragment Messenger messenger = new Messenger(returnHandler); DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger, - keyRingRowIds, Id.type.public_key); + keyRingRowIds); deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog"); } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index c4097403c..5e7cabcac 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -237,25 +237,12 @@ public class ViewKeyActivity extends ActionBarActivity { Handler returnHandler = new Handler() { @Override public void handleMessage(Message message) { - if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) { - Bundle returnData = message.getData(); - if (returnData != null - && returnData.containsKey(DeleteKeyDialogFragment.MESSAGE_NOT_DELETED)) { - // we delete only this key, so MESSAGE_NOT_DELETED will solely contain this key - Toast.makeText(ViewKeyActivity.this, - getString(R.string.error_can_not_delete_contact) - + getResources() - .getQuantityString(R.plurals.error_can_not_delete_info, 1), - Toast.LENGTH_LONG).show(); - } else { - setResult(RESULT_CANCELED); - finish(); - } - } + setResult(RESULT_CANCELED); + finish(); } }; - mExportHelper.deleteKey(dataUri, Id.type.public_key, returnHandler); + mExportHelper.deleteKey(dataUri, returnHandler); } } diff --git a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java index 1bcf5b33c..76a69328a 100644 --- a/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java +++ b/OpenPGP-Keychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Dominik Schürmann + * Copyright (C) 2013-2014 Dominik Schürmann * * 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 @@ -14,7 +14,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - package org.sufficientlysecure.keychain.ui.dialog; import android.app.AlertDialog; @@ -28,6 +27,11 @@ import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentActivity; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.CheckBox; +import android.widget.LinearLayout; +import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Id; import org.sufficientlysecure.keychain.R; @@ -35,148 +39,167 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.util.Log; - import java.util.ArrayList; public class DeleteKeyDialogFragment extends DialogFragment { private static final String ARG_MESSENGER = "messenger"; private static final String ARG_DELETE_KEY_RING_ROW_IDS = "delete_file"; - private static final String ARG_KEY_TYPE = "key_type"; public static final int MESSAGE_OKAY = 1; + public static final int MESSAGE_ERROR = 0; + + private boolean isSingleSelection = false; - public static final String MESSAGE_NOT_DELETED = "not_deleted"; + private TextView mainMessage; + private CheckBox checkDeleteSecret; + private LinearLayout deleteSecretKeyView; + private View inflateView; private Messenger mMessenger; /** * Creates new instance of this delete file dialog fragment */ - public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] keyRingRowIds, - int keyType) { + public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] keyRingRowIds + ) { DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_MESSENGER, messenger); args.putLongArray(ARG_DELETE_KEY_RING_ROW_IDS, keyRingRowIds); - args.putInt(ARG_KEY_TYPE, keyType); + //We don't need the key type frag.setArguments(args); return frag; } - /** - * Creates dialog - */ + @Override public Dialog onCreateDialog(Bundle savedInstanceState) { + final FragmentActivity activity = getActivity(); mMessenger = getArguments().getParcelable(ARG_MESSENGER); final long[] keyRingRowIds = getArguments().getLongArray(ARG_DELETE_KEY_RING_ROW_IDS); - final int keyType = getArguments().getInt(ARG_KEY_TYPE); AlertDialog.Builder builder = new AlertDialog.Builder(activity); + + //Setup custom View to display in AlertDialog + LayoutInflater inflater = activity.getLayoutInflater(); + inflateView = inflater.inflate(R.layout.view_key_delete_fragment, null); + builder.setView(inflateView); + + deleteSecretKeyView = (LinearLayout) inflateView.findViewById(R.id.deleteSecretKeyView); + mainMessage = (TextView) inflateView.findViewById(R.id.mainMessage); + checkDeleteSecret = (CheckBox) inflateView.findViewById(R.id.checkDeleteSecret); + builder.setTitle(R.string.warning); + //If only a single key has been selected if (keyRingRowIds.length == 1) { Uri dataUri; - if (keyType == Id.type.public_key) { - dataUri = KeychainContract.KeyRings.buildPublicKeyRingsUri(String.valueOf(keyRingRowIds[0])); + ArrayList publicKeyRings; //Any one will do + isSingleSelection = true; + + long selectedRow = keyRingRowIds[0]; + long keyType; + publicKeyRings = ProviderHelper.getPublicKeyRingsRowIds(activity); + + if (publicKeyRings.contains(selectedRow)) { + //TODO Should be a better method to do this other than getting all the KeyRings + dataUri = KeychainContract.KeyRings.buildPublicKeyRingsUri(String.valueOf(selectedRow)); + keyType = Id.type.public_key; } else { - dataUri = KeychainContract.KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowIds[0])); + dataUri = KeychainContract.KeyRings.buildSecretKeyRingsUri(String.valueOf(selectedRow)); + keyType = Id.type.secret_key; } + String userId = ProviderHelper.getUserId(activity, dataUri); + //Hide the Checkbox and TextView since this is a single selection,user will be notified thru message + deleteSecretKeyView.setVisibility(View.GONE); + //Set message depending on which key it is. + mainMessage.setText(getString(keyType == Id.type.secret_key ? R.string.secret_key_deletion_confirmation + : R.string.public_key_deletetion_confirmation, userId)); + - builder.setMessage(getString( - keyType == Id.type.public_key ? R.string.key_deletion_confirmation - : R.string.secret_key_deletion_confirmation, userId)); } else { - builder.setMessage(R.string.key_deletion_confirmation_multi); + deleteSecretKeyView.setVisibility(View.VISIBLE); + mainMessage.setText(R.string.key_deletion_confirmation_multi); } + builder.setIcon(R.drawable.ic_dialog_alert_holo_light); builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int id) { - ArrayList notDeleted = new ArrayList(); - - if (keyType == Id.type.public_key) { - Uri queryUri = KeychainContract.KeyRings.buildPublicKeyRingsUri(); - String[] projection = new String[]{ - KeychainContract.KeyRings._ID, // 0 - KeychainContract.KeyRings.MASTER_KEY_ID, // 1 - KeychainContract.UserIds.USER_ID // 2 - }; - - // make selection with all entries where _ID is one of the given row ids - String selection = KeychainDatabase.Tables.KEY_RINGS + "." + - KeychainContract.KeyRings._ID + " IN("; - String selectionIDs = ""; - for (int i = 0; i < keyRingRowIds.length; i++) { - selectionIDs += "'" + String.valueOf(keyRingRowIds[i]) + "'"; - if (i + 1 < keyRingRowIds.length) { - selectionIDs += ","; + @Override + 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 + String selection = KeychainDatabase.Tables.KEY_RINGS + "." + + KeychainContract.KeyRings._ID + " IN("; + String selectionIDs = ""; + for (int i = 0; i < keyRingRowIds.length; i++) { + selectionIDs += "'" + String.valueOf(keyRingRowIds[i]) + "'"; + if (i + 1 < keyRingRowIds.length) + selectionIDs += ","; } - } - selection += selectionIDs + ")"; - - Cursor cursor = activity.getContentResolver().query(queryUri, projection, - selection, null, null); - - long rowId; - long masterKeyId; - String userId; - try { - while (cursor != null && cursor.moveToNext()) { - rowId = cursor.getLong(0); - masterKeyId = cursor.getLong(1); - userId = cursor.getString(2); - - Log.d(Constants.TAG, "rowId: " + rowId + ", masterKeyId: " + masterKeyId - + ", userId: " + userId); - - // check if a corresponding secret key exists... - Cursor secretCursor = activity.getContentResolver().query( - KeychainContract.KeyRings - .buildSecretKeyRingsByMasterKeyIdUri( - String.valueOf(masterKeyId)), - null, null, null, null - ); - if (secretCursor != null && secretCursor.getCount() > 0) { - notDeleted.add(userId); - } else { - // it is okay to delete this key, no secret key found! - ProviderHelper.deletePublicKeyRing(activity, rowId); + 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 (checkDeleteSecret.isChecked() || isSingleSelection) { + ProviderHelper.deleteUnifiedKeyRing(activity, String.valueOf(masterKeyId), true); + } + } else { + ProviderHelper.deleteUnifiedKeyRing(activity, String.valueOf(masterKeyId), false); + } } - if (secretCursor != null) { - secretCursor.close(); + + //Check if the selected rows have actually been deleted + cursor = activity.getContentResolver().query(queryUri, projection, selection, null, null); + if (cursor == null || cursor.getCount() == 0 || !checkDeleteSecret.isChecked()) { + isSuccessfullyDeleted = true; + } + + } finally { + if (cursor != null) { + cursor.close(); } + } - } finally { - if (cursor != null) { - cursor.close(); + + dismiss(); + + if (isSuccessfullyDeleted) { + sendMessageToHandler(MESSAGE_OKAY, null); + } else { + sendMessageToHandler(MESSAGE_ERROR, null); } } - } else { - for (long keyRowId : keyRingRowIds) { - ProviderHelper.deleteSecretKeyRing(activity, keyRowId); - } - } - - dismiss(); - if (notDeleted.size() > 0) { - Bundle data = new Bundle(); - data.putStringArrayList(MESSAGE_NOT_DELETED, notDeleted); - sendMessageToHandler(MESSAGE_OKAY, data); - } else { - sendMessageToHandler(MESSAGE_OKAY, null); } - } - }); + ); builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override @@ -198,7 +221,6 @@ public class DeleteKeyDialogFragment extends DialogFragment { if (data != null) { msg.setData(data); } - try { mMessenger.send(msg); } catch (RemoteException e) { @@ -207,4 +229,5 @@ public class DeleteKeyDialogFragment extends DialogFragment { Log.w(Constants.TAG, "Messenger is null!", e); } } -} + +} \ No newline at end of file -- cgit v1.2.3