db-overhaul: fix key export (and some export-related ui changes)

This commit is contained in:
Vincent Breitmoser 2014-04-04 18:49:45 +02:00
parent cf76a8553a
commit d7c2488a0f
8 changed files with 76 additions and 80 deletions

View File

@ -61,8 +61,8 @@ public class ExportHelper {
/**
* Show dialog where to export keys
*/
public void showExportKeysDialog(final long[] masterKeyIds, final int keyType,
final String exportFilename, final String checkboxString) {
public void showExportKeysDialog(final long[] masterKeyIds, final String exportFilename,
final boolean showSecretCheckbox) {
mExportFilename = exportFilename;
// Message is received after file is selected
@ -71,14 +71,9 @@ public class ExportHelper {
public void handleMessage(Message message) {
if (message.what == FileDialogFragment.MESSAGE_OKAY) {
Bundle data = message.getData();
int type = keyType;
mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
if (data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED)) {
type = Id.type.public_secret_key;
}
exportKeys(masterKeyIds, type);
exportKeys(masterKeyIds, data.getBoolean(FileDialogFragment.MESSAGE_DATA_CHECKED));
}
}
};
@ -98,9 +93,11 @@ public class ExportHelper {
}
String message = mActivity.getString(R.string.specify_file_to_export_to);
String checkMsg = showSecretCheckbox ?
mActivity.getString(R.string.also_export_secret_keys) : null;
mFileDialog = FileDialogFragment.newInstance(messenger, title, message,
exportFilename, checkboxString);
exportFilename, checkMsg);
mFileDialog.show(mActivity.getSupportFragmentManager(), "fileDialog");
}
@ -110,7 +107,7 @@ public class ExportHelper {
/**
* Export keys
*/
public void exportKeys(long[] masterKeyIds, int keyType) {
public void exportKeys(long[] masterKeyIds, boolean exportSecret) {
Log.d(Constants.TAG, "exportKeys started");
// Send all information needed to service to export key in other thread
@ -122,7 +119,7 @@ public class ExportHelper {
Bundle data = new Bundle();
data.putString(KeychainIntentService.EXPORT_FILENAME, mExportFilename);
data.putInt(KeychainIntentService.EXPORT_KEY_TYPE, keyType);
data.putBoolean(KeychainIntentService.EXPORT_SECRET, exportSecret);
if (masterKeyIds == null) {
data.putBoolean(KeychainIntentService.EXPORT_ALL, true);

View File

@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.service;
import android.app.IntentService;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
@ -50,6 +51,8 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
import org.sufficientlysecure.keychain.util.HkpKeyServer;
@ -147,7 +150,7 @@ public class KeychainIntentService extends IntentService
// export key
public static final String EXPORT_OUTPUT_STREAM = "export_output_stream";
public static final String EXPORT_FILENAME = "export_filename";
public static final String EXPORT_KEY_TYPE = "export_key_type";
public static final String EXPORT_SECRET = "export_secret";
public static final String EXPORT_ALL = "export_all";
public static final String EXPORT_KEY_RING_MASTER_KEY_ID = "export_key_ring_id";
@ -635,19 +638,13 @@ public class KeychainIntentService extends IntentService
} else if (ACTION_EXPORT_KEYRING.equals(action)) {
try {
/* Input */
int keyType = Id.type.public_key;
if (data.containsKey(EXPORT_KEY_TYPE)) {
keyType = data.getInt(EXPORT_KEY_TYPE);
}
boolean exportSecret = data.getBoolean(EXPORT_SECRET, false);
long[] masterKeyIds = data.getLongArray(EXPORT_KEY_RING_MASTER_KEY_ID);
String outputFile = data.getString(EXPORT_FILENAME);
// If not exporting all keys get the masterKeyIds of the keys to export from the intent
boolean exportAll = data.getBoolean(EXPORT_ALL);
/* Operation */
// check if storage is ready
if (!FileHelper.isStorageMounted(outputFile)) {
throw new PgpGeneralException(getString(R.string.error_external_storage_not_ready));
@ -655,31 +652,30 @@ public class KeychainIntentService extends IntentService
ArrayList<Long> publicMasterKeyIds = new ArrayList<Long>();
ArrayList<Long> secretMasterKeyIds = new ArrayList<Long>();
// TODO redo
ArrayList<Long> allPublicMasterKeyIds = null; // ProviderHelper.getPublicKeyRingsMasterKeyIds(this);
ArrayList<Long> allSecretMasterKeyIds = null; // ProviderHelper.getSecretKeyRingsMasterKeyIds(this);
if (exportAll) {
// get all public key ring MasterKey ids
if (keyType == Id.type.public_key || keyType == Id.type.public_secret_key) {
publicMasterKeyIds = allPublicMasterKeyIds;
String selection = null;
if(!exportAll) {
selection = KeychainDatabase.Tables.KEYS + "." + KeyRings.MASTER_KEY_ID + " IN( ";
for(long l : masterKeyIds) {
selection += Long.toString(l) + ",";
}
// get all secret key ring MasterKey ids
if (keyType == Id.type.secret_key || keyType == Id.type.public_secret_key) {
secretMasterKeyIds = allSecretMasterKeyIds;
}
} else {
selection = selection.substring(0, selection.length()-1) + " )";
}
for (long masterKeyId : masterKeyIds) {
if ((keyType == Id.type.public_key || keyType == Id.type.public_secret_key)
&& allPublicMasterKeyIds.contains(masterKeyId)) {
publicMasterKeyIds.add(masterKeyId);
}
if ((keyType == Id.type.secret_key || keyType == Id.type.public_secret_key)
&& allSecretMasterKeyIds.contains(masterKeyId)) {
secretMasterKeyIds.add(masterKeyId);
}
}
Cursor cursor = getContentResolver().query(KeyRings.buildUnifiedKeyRingsUri(),
new String[]{ KeyRings.MASTER_KEY_ID, KeyRings.HAS_SECRET },
selection, null, null);
try {
cursor.moveToFirst();
do {
// export public either way
publicMasterKeyIds.add(cursor.getLong(0));
// add secret if available (and requested)
if(exportSecret && cursor.getInt(1) != 0)
secretMasterKeyIds.add(cursor.getLong(0));
} while(cursor.moveToNext());
} finally {
cursor.close();
}
PgpImportExport pgpImportExport = new PgpImportExport(this, this, this);

View File

@ -339,9 +339,8 @@ public class EditKeyActivity extends ActionBarActivity implements EditorListener
Toast.makeText(this, R.string.error_save_first, Toast.LENGTH_LONG).show();
} else {
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);
mExportHelper.showExportKeysDialog(
new long[] { masterKeyId }, Constants.Path.APP_DIR_FILE_SEC, true);
return true;
}
return true;

View File

@ -23,7 +23,6 @@ import android.view.Menu;
import android.view.MenuItem;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ExportHelper;
@ -55,26 +54,20 @@ public class KeyListActivity extends DrawerActivity {
switch (item.getItemId()) {
case R.id.menu_key_list_import:
callIntentForDrawerItem(Constants.DrawerItems.IMPORT_KEYS);
return true;
case R.id.menu_key_list_create:
createKey();
return true;
case R.id.menu_key_list_create_expert:
createKeyExpert();
return true;
case R.id.menu_key_list_export_public:
mExportHelper.showExportKeysDialog(null,
Id.type.public_key, Constants.Path.APP_DIR_FILE_PUB, null);
case R.id.menu_key_list_export:
mExportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE_PUB, true);
return true;
case R.id.menu_key_list_secret_export:
mExportHelper.showExportKeysDialog(null, Id.type.secret_key,
Constants.Path.APP_DIR_FILE_SEC, null);
return true;
default:
return super.onOptionsItemSelected(item);
}

View File

@ -60,7 +60,6 @@ import org.sufficientlysecure.keychain.helper.ExportHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.ui.adapter.HighlightQueryCursorAdapter;
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
@ -68,7 +67,6 @@ import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
import java.util.ArrayList;
import java.util.HashMap;
/**
@ -194,10 +192,8 @@ public class KeyListFragment extends Fragment
case R.id.menu_key_list_multi_export: {
ids = mAdapter.getCurrentSelectedMasterKeyIds();
ExportHelper mExportHelper = new ExportHelper((ActionBarActivity) getActivity());
mExportHelper
.showExportKeysDialog(ids, Id.type.public_key,
Constants.Path.APP_DIR_FILE_PUB,
getString(R.string.also_export_secret_keys));
mExportHelper.showExportKeysDialog(
ids, Constants.Path.APP_DIR_FILE_PUB, mAdapter.isAnySecretSelected());
break;
}
case R.id.menu_key_list_multi_select_all: {
@ -525,6 +521,13 @@ public class KeyListFragment extends Fragment
}
public boolean isSecretAvailable(int id) {
if (!mCursor.moveToPosition(id)) {
throw new IllegalStateException("couldn't move cursor to position " + id);
}
return mCursor.getInt(INDEX_HAS_SECRET) != 0;
}
public long getMasterKeyId(int id) {
if (!mCursor.moveToPosition(id)) {
throw new IllegalStateException("couldn't move cursor to position " + id);
@ -633,6 +636,14 @@ public class KeyListFragment extends Fragment
notifyDataSetChanged();
}
public boolean isAnySecretSelected() {
for (int pos : mSelection.keySet()) {
if(mAdapter.isSecretAvailable(pos))
return true;
}
return false;
}
public long[] getCurrentSelectedMasterKeyIds() {
long[] ids = new long[mSelection.size()];
int i = 0;

View File

@ -42,7 +42,6 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.TabsAdapter;
import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
@ -120,10 +119,12 @@ public class ViewKeyActivity extends ActionBarActivity {
uploadToKeyserver(mDataUri);
return true;
case R.id.menu_key_view_export_file:
long masterKeyId = Long.valueOf(mDataUri.getLastPathSegment());
long[] ids = new long[]{masterKeyId};
mExportHelper.showExportKeysDialog(ids, Id.type.public_key,
Constants.Path.APP_DIR_FILE_PUB, null);
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()
);
return true;
case R.id.menu_key_view_share_default_fingerprint:
shareKey(mDataUri, true);

View File

@ -81,6 +81,9 @@ 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);
@ -227,9 +230,9 @@ public class ViewKeyMainFragment extends Fragment implements
mEmail.setText(mainUserId[1]);
mComment.setText(mainUserId[2]);
if (data.getInt(INDEX_UNIFIED_HAS_SECRET) > 0) {
// set this attribute. this is a LITTLE unclean, but we have the info available
// right here, so why not.
if (data.getInt(INDEX_UNIFIED_HAS_SECRET) != 0) {
mSecretAvailable = true;
mSecretKey.setTextColor(getResources().getColor(R.color.emphasis));
mSecretKey.setText(R.string.secret_key_yes);
@ -244,6 +247,8 @@ public class ViewKeyMainFragment extends Fragment implements
}
});
} else {
mSecretAvailable = false;
mSecretKey.setTextColor(Color.BLACK);
mSecretKey.setText(getResources().getString(R.string.secret_key_no));
@ -332,6 +337,11 @@ 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);

View File

@ -38,17 +38,6 @@
app:showAsAction="ifRoom|withText"
android:icon="@drawable/ic_action_import_export"
android:title="@string/menu_export_keys">
<menu>
<item
android:id="@+id/menu_key_list_export_public"
app:showAsAction="never"
android:title="@string/menu_export_public_keys" />
<item
android:id="@+id/menu_key_list_secret_export"
app:showAsAction="never"
android:title="@string/menu_export_secret_keys" />
</menu>
</item>
</menu>