2010-04-06 19:54:51 +00:00
|
|
|
/*
|
2012-04-12 19:44:00 +02:00
|
|
|
* Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
|
2010-04-06 19:54:51 +00:00
|
|
|
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-01-16 14:31:16 +01:00
|
|
|
package org.sufficientlysecure.keychain.ui;
|
2012-04-14 16:18:06 +02:00
|
|
|
|
2013-09-06 14:42:48 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Iterator;
|
|
|
|
|
import java.util.Vector;
|
|
|
|
|
|
2011-11-03 22:15:31 +01:00
|
|
|
import org.spongycastle.openpgp.PGPSecretKey;
|
|
|
|
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
2013-01-16 14:31:16 +01:00
|
|
|
import org.sufficientlysecure.keychain.Constants;
|
|
|
|
|
import org.sufficientlysecure.keychain.Id;
|
2013-09-06 14:42:48 +02:00
|
|
|
import org.sufficientlysecure.keychain.R;
|
2013-09-08 15:30:05 +02:00
|
|
|
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
|
2013-01-16 14:31:16 +01:00
|
|
|
import org.sufficientlysecure.keychain.helper.PgpConversionHelper;
|
|
|
|
|
import org.sufficientlysecure.keychain.helper.PgpHelper;
|
|
|
|
|
import org.sufficientlysecure.keychain.helper.PgpMain;
|
|
|
|
|
import org.sufficientlysecure.keychain.helper.PgpMain.PgpGeneralException;
|
|
|
|
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
|
|
|
|
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
|
|
|
|
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
|
|
|
|
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
|
|
|
|
import org.sufficientlysecure.keychain.ui.widget.KeyEditor;
|
|
|
|
|
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;
|
2012-03-11 17:33:40 +01:00
|
|
|
|
2012-04-25 15:10:12 +02:00
|
|
|
import android.app.ProgressDialog;
|
2010-04-06 19:54:51 +00:00
|
|
|
import android.content.Context;
|
|
|
|
|
import android.content.Intent;
|
|
|
|
|
import android.os.Bundle;
|
2012-09-05 22:35:55 +02:00
|
|
|
import android.os.Handler;
|
2010-04-06 19:54:51 +00:00
|
|
|
import android.os.Message;
|
2012-04-20 12:12:07 +02:00
|
|
|
import android.os.Messenger;
|
2010-04-06 19:54:51 +00:00
|
|
|
import android.view.LayoutInflater;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.View.OnClickListener;
|
2013-09-06 14:42:48 +02:00
|
|
|
import android.view.ViewGroup;
|
2010-04-06 19:54:51 +00:00
|
|
|
import android.widget.Button;
|
2012-04-12 19:44:00 +02:00
|
|
|
import android.widget.CheckBox;
|
|
|
|
|
import android.widget.CompoundButton;
|
2013-09-06 14:42:48 +02:00
|
|
|
import android.widget.CompoundButton.OnCheckedChangeListener;
|
2010-04-06 19:54:51 +00:00
|
|
|
import android.widget.LinearLayout;
|
2013-09-06 14:42:48 +02:00
|
|
|
import android.widget.TextView;
|
2010-04-06 19:54:51 +00:00
|
|
|
import android.widget.Toast;
|
|
|
|
|
|
2013-09-06 14:42:48 +02:00
|
|
|
import com.actionbarsherlock.app.ActionBar;
|
|
|
|
|
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
2011-11-03 22:15:31 +01:00
|
|
|
|
2012-04-25 19:09:24 +02:00
|
|
|
public class EditKeyActivity extends SherlockFragmentActivity {
|
2012-06-20 15:27:45 +03:00
|
|
|
|
|
|
|
|
// possible intent actions for this activity
|
2013-01-17 01:53:49 +01:00
|
|
|
public static final String ACTION_CREATE_KEY = Constants.INTENT_PREFIX + "CREATE_KEYRING";
|
|
|
|
|
public static final String ACTION_EDIT_KEY = Constants.INTENT_PREFIX + "EDIT_KEYRING";
|
2012-06-20 15:27:45 +03:00
|
|
|
|
2012-06-20 15:55:36 +03:00
|
|
|
// possible extra keys
|
|
|
|
|
public static final String EXTRA_USER_IDS = "userIds";
|
|
|
|
|
public static final String EXTRA_NO_PASSPHRASE = "noPassphrase";
|
|
|
|
|
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generateDefaultKeys";
|
2013-01-18 00:33:20 +01:00
|
|
|
public static final String EXTRA_MASTER_KEY_ID = "masterKeyId";
|
2013-03-21 14:18:38 +00:00
|
|
|
public static final String EXTRA_MASTER_CAN_SIGN = "masterCanSign";
|
2012-06-20 15:55:36 +03:00
|
|
|
|
2012-12-12 19:14:09 +01:00
|
|
|
// results when saving key
|
|
|
|
|
public static final String RESULT_EXTRA_MASTER_KEY_ID = "masterKeyId";
|
|
|
|
|
public static final String RESULT_EXTRA_USER_ID = "userId";
|
|
|
|
|
|
2012-04-14 15:25:33 +02:00
|
|
|
private ActionBar mActionBar;
|
2010-04-06 19:54:51 +00:00
|
|
|
|
|
|
|
|
private PGPSecretKeyRing mKeyRing = null;
|
|
|
|
|
|
2012-04-25 17:54:02 +02:00
|
|
|
private SectionView mUserIdsView;
|
|
|
|
|
private SectionView mKeysView;
|
2010-04-06 19:54:51 +00:00
|
|
|
|
2010-05-16 13:35:16 +00:00
|
|
|
private String mCurrentPassPhrase = null;
|
2010-04-06 19:54:51 +00:00
|
|
|
private String mNewPassPhrase = null;
|
|
|
|
|
|
2010-07-23 12:57:02 +00:00
|
|
|
private Button mChangePassPhrase;
|
|
|
|
|
|
2012-04-13 16:54:50 +02:00
|
|
|
private CheckBox mNoPassphrase;
|
|
|
|
|
|
2012-04-25 17:54:02 +02:00
|
|
|
Vector<String> mUserIds;
|
|
|
|
|
Vector<PGPSecretKey> mKeys;
|
|
|
|
|
Vector<Integer> mKeysUsages;
|
2013-03-21 14:18:38 +00:00
|
|
|
boolean masterCanSign = true;
|
2012-04-25 15:10:12 +02:00
|
|
|
|
2012-04-25 18:59:51 +02:00
|
|
|
// will be set to false to build layout later in handler
|
2012-04-25 18:37:58 +02:00
|
|
|
private boolean mBuildLayout = true;
|
|
|
|
|
|
2010-04-06 19:54:51 +00:00
|
|
|
@Override
|
|
|
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
2012-11-16 02:34:21 +01:00
|
|
|
|
2013-09-06 14:32:12 +02:00
|
|
|
// TODO: disabled, old API!
|
2012-11-16 02:34:21 +01:00
|
|
|
// check permissions for intent actions without user interaction
|
2013-09-06 14:32:12 +02:00
|
|
|
// String[] restrictedActions = new String[] { ACTION_CREATE_KEY };
|
|
|
|
|
// OtherHelper.checkPackagePermissionForActions(this, this.getCallingPackage(),
|
|
|
|
|
// Constants.PERMISSION_ACCESS_API, getIntent().getAction(), restrictedActions);
|
2012-11-16 02:34:21 +01:00
|
|
|
|
2013-09-06 14:42:48 +02:00
|
|
|
// Inflate a "Done"/"Cancel" custom action bar view
|
|
|
|
|
final LayoutInflater inflater = (LayoutInflater) getSupportActionBar().getThemedContext()
|
|
|
|
|
.getSystemService(LAYOUT_INFLATER_SERVICE);
|
|
|
|
|
final View customActionBarView = inflater.inflate(
|
|
|
|
|
R.layout.actionbar_custom_view_done_cancel, null);
|
|
|
|
|
|
|
|
|
|
((TextView) customActionBarView.findViewById(R.id.actionbar_done_text))
|
|
|
|
|
.setText(R.string.btn_save);
|
|
|
|
|
customActionBarView.findViewById(R.id.actionbar_done).setOnClickListener(
|
|
|
|
|
new View.OnClickListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
// save
|
|
|
|
|
saveClicked();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
((TextView) customActionBarView.findViewById(R.id.actionbar_cancel_text))
|
|
|
|
|
.setText(R.string.btn_doNotSave);
|
|
|
|
|
customActionBarView.findViewById(R.id.actionbar_cancel).setOnClickListener(
|
|
|
|
|
new View.OnClickListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onClick(View v) {
|
|
|
|
|
// cancel
|
|
|
|
|
cancelClicked();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Show the custom action bar view and hide the normal Home icon and title.
|
|
|
|
|
final ActionBar actionBar = getSupportActionBar();
|
|
|
|
|
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM
|
|
|
|
|
| ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE);
|
|
|
|
|
actionBar.setCustomView(customActionBarView, new ActionBar.LayoutParams(
|
|
|
|
|
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
|
|
|
|
|
2010-04-06 19:54:51 +00:00
|
|
|
setContentView(R.layout.edit_key);
|
|
|
|
|
|
2012-04-14 15:25:33 +02:00
|
|
|
mActionBar = getSupportActionBar();
|
2012-04-25 15:10:12 +02:00
|
|
|
mActionBar.setDisplayShowTitleEnabled(true);
|
|
|
|
|
|
2012-09-12 13:51:48 +02:00
|
|
|
// set actionbar without home button if called from another app
|
2013-09-08 15:30:05 +02:00
|
|
|
ActionBarHelper.setBackButton(this);
|
2012-04-14 15:25:33 +02:00
|
|
|
|
|
|
|
|
// find views
|
|
|
|
|
mChangePassPhrase = (Button) findViewById(R.id.edit_key_btn_change_pass_phrase);
|
|
|
|
|
mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase);
|
|
|
|
|
|
2012-04-25 17:54:02 +02:00
|
|
|
mUserIds = new Vector<String>();
|
|
|
|
|
mKeys = new Vector<PGPSecretKey>();
|
|
|
|
|
mKeysUsages = new Vector<Integer>();
|
2010-04-06 19:54:51 +00:00
|
|
|
|
2012-04-14 15:25:33 +02:00
|
|
|
// Catch Intents opened from other apps
|
2012-09-13 18:24:10 +02:00
|
|
|
Intent intent = getIntent();
|
|
|
|
|
String action = intent.getAction();
|
|
|
|
|
if (ACTION_CREATE_KEY.equals(action)) {
|
|
|
|
|
handleActionCreateKey(intent);
|
|
|
|
|
} else if (ACTION_EDIT_KEY.equals(action)) {
|
|
|
|
|
handleActionEditKey(intent);
|
2012-04-12 15:23:00 +02:00
|
|
|
}
|
|
|
|
|
|
2010-07-23 12:57:02 +00:00
|
|
|
mChangePassPhrase.setOnClickListener(new OnClickListener() {
|
|
|
|
|
public void onClick(View v) {
|
2012-09-05 22:35:55 +02:00
|
|
|
showSetPassphraseDialog();
|
2010-07-23 12:57:02 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2012-04-12 19:44:00 +02:00
|
|
|
// disable passphrase when no passphrase checkobox is checked!
|
2012-04-13 16:54:50 +02:00
|
|
|
mNoPassphrase.setOnCheckedChangeListener(new OnCheckedChangeListener() {
|
2012-04-12 19:44:00 +02:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
|
|
|
|
if (isChecked) {
|
2012-04-13 16:54:50 +02:00
|
|
|
// remove passphrase
|
|
|
|
|
mNewPassPhrase = null;
|
|
|
|
|
|
2012-04-12 19:44:00 +02:00
|
|
|
mChangePassPhrase.setVisibility(View.GONE);
|
|
|
|
|
} else {
|
|
|
|
|
mChangePassPhrase.setVisibility(View.VISIBLE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2012-04-25 18:37:58 +02:00
|
|
|
if (mBuildLayout) {
|
|
|
|
|
buildLayout();
|
|
|
|
|
}
|
2012-04-25 17:54:02 +02:00
|
|
|
}
|
|
|
|
|
|
2012-09-13 18:24:10 +02:00
|
|
|
/**
|
|
|
|
|
* Handle intent action to create new key
|
|
|
|
|
*
|
|
|
|
|
* @param intent
|
|
|
|
|
*/
|
|
|
|
|
private void handleActionCreateKey(Intent intent) {
|
|
|
|
|
Bundle extras = intent.getExtras();
|
|
|
|
|
|
|
|
|
|
mActionBar.setTitle(R.string.title_createKey);
|
|
|
|
|
|
|
|
|
|
mCurrentPassPhrase = "";
|
|
|
|
|
|
|
|
|
|
if (extras != null) {
|
|
|
|
|
// if userId is given, prefill the fields
|
|
|
|
|
if (extras.containsKey(EXTRA_USER_IDS)) {
|
|
|
|
|
Log.d(Constants.TAG, "UserIds are given!");
|
|
|
|
|
mUserIds.add(extras.getString(EXTRA_USER_IDS));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if no passphrase is given
|
|
|
|
|
if (extras.containsKey(EXTRA_NO_PASSPHRASE)) {
|
|
|
|
|
boolean noPassphrase = extras.getBoolean(EXTRA_NO_PASSPHRASE);
|
|
|
|
|
if (noPassphrase) {
|
|
|
|
|
// check "no passphrase" checkbox and remove button
|
|
|
|
|
mNoPassphrase.setChecked(true);
|
|
|
|
|
mChangePassPhrase.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generate key
|
|
|
|
|
if (extras.containsKey(EXTRA_GENERATE_DEFAULT_KEYS)) {
|
|
|
|
|
boolean generateDefaultKeys = extras.getBoolean(EXTRA_GENERATE_DEFAULT_KEYS);
|
|
|
|
|
if (generateDefaultKeys) {
|
|
|
|
|
|
|
|
|
|
// build layout in handler after generating keys not directly in onCreate
|
|
|
|
|
mBuildLayout = false;
|
|
|
|
|
|
|
|
|
|
// Send all information needed to service generate keys in other thread
|
2013-01-16 14:31:16 +01:00
|
|
|
Intent serviceIntent = new Intent(this, KeychainIntentService.class);
|
2013-07-23 07:49:34 -05:00
|
|
|
serviceIntent.setAction(KeychainIntentService.ACTION_GENERATE_DEFAULT_RSA_KEYS);
|
2012-09-13 18:24:10 +02:00
|
|
|
|
|
|
|
|
// fill values for this action
|
|
|
|
|
Bundle data = new Bundle();
|
2013-01-16 14:31:16 +01:00
|
|
|
data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE,
|
2012-12-12 19:14:09 +01:00
|
|
|
mCurrentPassPhrase);
|
2012-09-13 18:24:10 +02:00
|
|
|
|
2013-01-16 14:31:16 +01:00
|
|
|
serviceIntent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
2012-09-13 18:24:10 +02:00
|
|
|
|
|
|
|
|
// Message is received after generating is done in ApgService
|
2013-01-18 00:36:30 +01:00
|
|
|
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
|
|
|
|
this, R.string.progress_generating, ProgressDialog.STYLE_SPINNER) {
|
2012-09-13 18:24:10 +02:00
|
|
|
public void handleMessage(Message message) {
|
|
|
|
|
// handle messages by standard ApgHandler first
|
|
|
|
|
super.handleMessage(message);
|
|
|
|
|
|
2013-01-16 14:31:16 +01:00
|
|
|
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
|
2012-09-13 18:24:10 +02:00
|
|
|
// get new key from data bundle returned from service
|
|
|
|
|
Bundle data = message.getData();
|
2013-01-16 14:31:16 +01:00
|
|
|
PGPSecretKeyRing masterKeyRing = (PGPSecretKeyRing) PgpConversionHelper
|
2012-10-31 00:39:32 +01:00
|
|
|
.BytesToPGPKeyRing(data
|
2013-01-16 14:31:16 +01:00
|
|
|
.getByteArray(KeychainIntentService.RESULT_NEW_KEY));
|
|
|
|
|
PGPSecretKeyRing subKeyRing = (PGPSecretKeyRing) PgpConversionHelper
|
2012-10-31 00:39:32 +01:00
|
|
|
.BytesToPGPKeyRing(data
|
2013-01-16 14:31:16 +01:00
|
|
|
.getByteArray(KeychainIntentService.RESULT_NEW_KEY2));
|
2012-09-13 18:24:10 +02:00
|
|
|
|
|
|
|
|
// add master key
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
|
Iterator<PGPSecretKey> masterIt = masterKeyRing.getSecretKeys();
|
|
|
|
|
mKeys.add(masterIt.next());
|
|
|
|
|
mKeysUsages.add(Id.choice.usage.sign_only);
|
|
|
|
|
|
|
|
|
|
// add sub key
|
|
|
|
|
@SuppressWarnings("unchecked")
|
|
|
|
|
Iterator<PGPSecretKey> subIt = subKeyRing.getSecretKeys();
|
|
|
|
|
subIt.next(); // masterkey
|
|
|
|
|
mKeys.add(subIt.next());
|
|
|
|
|
mKeysUsages.add(Id.choice.usage.encrypt_only);
|
|
|
|
|
|
|
|
|
|
buildLayout();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Create a new Messenger for the communication back
|
|
|
|
|
Messenger messenger = new Messenger(saveHandler);
|
2013-01-16 14:31:16 +01:00
|
|
|
serviceIntent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
|
2012-09-13 18:24:10 +02:00
|
|
|
|
|
|
|
|
saveHandler.showProgressDialog(this);
|
|
|
|
|
|
|
|
|
|
// start service with intent
|
|
|
|
|
startService(serviceIntent);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Handle intent action to edit existing key
|
|
|
|
|
*
|
|
|
|
|
* @param intent
|
|
|
|
|
*/
|
2012-12-14 19:16:10 +01:00
|
|
|
@SuppressWarnings("unchecked")
|
2012-09-13 18:24:10 +02:00
|
|
|
private void handleActionEditKey(Intent intent) {
|
|
|
|
|
Bundle extras = intent.getExtras();
|
|
|
|
|
|
|
|
|
|
mActionBar.setTitle(R.string.title_editKey);
|
|
|
|
|
|
2013-01-16 14:31:16 +01:00
|
|
|
mCurrentPassPhrase = PgpMain.getEditPassPhrase();
|
2012-09-13 18:24:10 +02:00
|
|
|
if (mCurrentPassPhrase == null) {
|
|
|
|
|
mCurrentPassPhrase = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mCurrentPassPhrase.equals("")) {
|
|
|
|
|
// check "no passphrase" checkbox and remove button
|
|
|
|
|
mNoPassphrase.setChecked(true);
|
|
|
|
|
mChangePassPhrase.setVisibility(View.GONE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (extras != null) {
|
2013-03-21 14:18:38 +00:00
|
|
|
if (extras.containsKey(EXTRA_MASTER_CAN_SIGN)) {
|
|
|
|
|
masterCanSign = extras.getBoolean(EXTRA_MASTER_CAN_SIGN);
|
|
|
|
|
}
|
2013-01-18 00:33:20 +01:00
|
|
|
if (extras.containsKey(EXTRA_MASTER_KEY_ID)) {
|
2013-01-18 00:36:30 +01:00
|
|
|
long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
|
2012-09-13 18:24:10 +02:00
|
|
|
|
2013-01-18 00:36:30 +01:00
|
|
|
if (masterKeyId != 0) {
|
2012-09-13 18:24:10 +02:00
|
|
|
PGPSecretKey masterKey = null;
|
2013-01-18 00:36:30 +01:00
|
|
|
mKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this, masterKeyId);
|
2012-09-13 18:24:10 +02:00
|
|
|
if (mKeyRing != null) {
|
2013-01-16 14:31:16 +01:00
|
|
|
masterKey = PgpHelper.getMasterKey(mKeyRing);
|
2012-09-13 18:24:10 +02:00
|
|
|
for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(
|
|
|
|
|
mKeyRing.getSecretKeys())) {
|
|
|
|
|
mKeys.add(key);
|
|
|
|
|
mKeysUsages.add(-1); // get usage when view is created
|
|
|
|
|
}
|
2013-01-18 00:36:30 +01:00
|
|
|
} else {
|
|
|
|
|
Log.e(Constants.TAG, "Keyring not found with masterKeyId: " + masterKeyId);
|
|
|
|
|
Toast.makeText(this, R.string.error_noSecretKeyFound, Toast.LENGTH_LONG)
|
|
|
|
|
.show();
|
2012-09-13 18:24:10 +02:00
|
|
|
}
|
|
|
|
|
if (masterKey != null) {
|
|
|
|
|
for (String userId : new IterableIterator<String>(masterKey.getUserIDs())) {
|
|
|
|
|
Log.d(Constants.TAG, "Added userId " + userId);
|
|
|
|
|
mUserIds.add(userId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-05 22:35:55 +02:00
|
|
|
/**
|
|
|
|
|
* Shows the dialog to set a new passphrase
|
|
|
|
|
*/
|
|
|
|
|
private void showSetPassphraseDialog() {
|
|
|
|
|
// Message is received after passphrase is cached
|
|
|
|
|
Handler returnHandler = new Handler() {
|
|
|
|
|
@Override
|
|
|
|
|
public void handleMessage(Message message) {
|
|
|
|
|
if (message.what == SetPassphraseDialogFragment.MESSAGE_OKAY) {
|
|
|
|
|
Bundle data = message.getData();
|
|
|
|
|
|
|
|
|
|
// set new returned passphrase!
|
|
|
|
|
mNewPassPhrase = data
|
|
|
|
|
.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE);
|
|
|
|
|
|
|
|
|
|
updatePassPhraseButtonText();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Create a new Messenger for the communication back
|
|
|
|
|
Messenger messenger = new Messenger(returnHandler);
|
|
|
|
|
|
|
|
|
|
// set title based on isPassphraseSet()
|
|
|
|
|
int title = -1;
|
|
|
|
|
if (isPassphraseSet()) {
|
|
|
|
|
title = R.string.title_changePassPhrase;
|
|
|
|
|
} else {
|
|
|
|
|
title = R.string.title_setPassPhrase;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SetPassphraseDialogFragment setPassphraseDialog = SetPassphraseDialogFragment.newInstance(
|
|
|
|
|
messenger, title);
|
|
|
|
|
|
|
|
|
|
setPassphraseDialog.show(getSupportFragmentManager(), "setPassphraseDialog");
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-25 17:54:02 +02:00
|
|
|
/**
|
|
|
|
|
* Build layout based on mUserId, mKeys and mKeysUsages Vectors. It creates Views for every user
|
|
|
|
|
* id and key.
|
|
|
|
|
*/
|
|
|
|
|
private void buildLayout() {
|
2012-04-12 15:23:00 +02:00
|
|
|
// Build layout based on given userIds and keys
|
2012-03-09 16:27:29 +01:00
|
|
|
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
2010-04-06 19:54:51 +00:00
|
|
|
|
2012-04-12 19:44:00 +02:00
|
|
|
LinearLayout container = (LinearLayout) findViewById(R.id.edit_key_container);
|
2012-04-25 17:54:02 +02:00
|
|
|
mUserIdsView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
|
|
|
|
mUserIdsView.setType(Id.type.user_id);
|
2013-03-21 14:18:38 +00:00
|
|
|
mUserIdsView.setCanEdit(masterCanSign);
|
2012-04-25 17:54:02 +02:00
|
|
|
mUserIdsView.setUserIds(mUserIds);
|
|
|
|
|
container.addView(mUserIdsView);
|
|
|
|
|
mKeysView = (SectionView) inflater.inflate(R.layout.edit_key_section, container, false);
|
|
|
|
|
mKeysView.setType(Id.type.key);
|
2013-03-21 14:18:38 +00:00
|
|
|
mKeysView.setCanEdit(masterCanSign);
|
2012-04-25 17:54:02 +02:00
|
|
|
mKeysView.setKeys(mKeys, mKeysUsages);
|
|
|
|
|
container.addView(mKeysView);
|
2010-04-06 19:54:51 +00:00
|
|
|
|
2010-07-23 12:57:02 +00:00
|
|
|
updatePassPhraseButtonText();
|
2010-04-06 19:54:51 +00:00
|
|
|
}
|
|
|
|
|
|
2010-05-19 14:51:58 +00:00
|
|
|
private long getMasterKeyId() {
|
2012-04-25 17:54:02 +02:00
|
|
|
if (mKeysView.getEditors().getChildCount() == 0) {
|
2010-05-15 15:19:56 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2012-04-25 17:54:02 +02:00
|
|
|
return ((KeyEditor) mKeysView.getEditors().getChildAt(0)).getValue().getKeyID();
|
2010-05-15 15:19:56 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-13 16:54:50 +02:00
|
|
|
public boolean isPassphraseSet() {
|
|
|
|
|
if (mNoPassphrase.isChecked()) {
|
|
|
|
|
return true;
|
|
|
|
|
} else if ((!mCurrentPassPhrase.equals(""))
|
|
|
|
|
|| (mNewPassPhrase != null && !mNewPassPhrase.equals(""))) {
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2010-04-06 19:54:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void saveClicked() {
|
2012-04-25 15:10:12 +02:00
|
|
|
try {
|
|
|
|
|
if (!isPassphraseSet()) {
|
2013-01-16 14:31:16 +01:00
|
|
|
throw new PgpMain.PgpGeneralException(this.getString(R.string.setAPassPhrase));
|
2012-04-20 12:12:07 +02:00
|
|
|
}
|
|
|
|
|
|
2012-04-25 15:10:12 +02:00
|
|
|
// Send all information needed to service to edit key in other thread
|
2013-01-16 14:31:16 +01:00
|
|
|
Intent intent = new Intent(this, KeychainIntentService.class);
|
2012-04-20 12:12:07 +02:00
|
|
|
|
2013-07-23 07:49:34 -05:00
|
|
|
intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING);
|
2012-04-20 12:12:07 +02:00
|
|
|
|
2012-04-25 15:10:12 +02:00
|
|
|
// fill values for this action
|
|
|
|
|
Bundle data = new Bundle();
|
2013-01-18 00:36:30 +01:00
|
|
|
data.putString(KeychainIntentService.SAVE_KEYRING_CURRENT_PASSPHRASE,
|
|
|
|
|
mCurrentPassPhrase);
|
2013-01-16 14:31:16 +01:00
|
|
|
data.putString(KeychainIntentService.SAVE_KEYRING_NEW_PASSPHRASE, mNewPassPhrase);
|
|
|
|
|
data.putStringArrayList(KeychainIntentService.SAVE_KEYRING_USER_IDS,
|
2012-12-12 19:14:09 +01:00
|
|
|
getUserIds(mUserIdsView));
|
2012-09-13 18:24:10 +02:00
|
|
|
ArrayList<PGPSecretKey> keys = getKeys(mKeysView);
|
2013-01-16 14:31:16 +01:00
|
|
|
data.putByteArray(KeychainIntentService.SAVE_KEYRING_KEYS,
|
|
|
|
|
PgpConversionHelper.PGPSecretKeyArrayListToBytes(keys));
|
|
|
|
|
data.putIntegerArrayList(KeychainIntentService.SAVE_KEYRING_KEYS_USAGES,
|
2012-12-12 19:14:09 +01:00
|
|
|
getKeysUsages(mKeysView));
|
2013-01-16 14:31:16 +01:00
|
|
|
data.putLong(KeychainIntentService.SAVE_KEYRING_MASTER_KEY_ID, getMasterKeyId());
|
2013-03-21 14:18:38 +00:00
|
|
|
data.putBoolean(KeychainIntentService.SAVE_KEYRING_CAN_SIGN, masterCanSign);
|
2012-04-25 15:10:12 +02:00
|
|
|
|
2013-01-16 14:31:16 +01:00
|
|
|
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
2012-04-25 15:10:12 +02:00
|
|
|
|
|
|
|
|
// Message is received after saving is done in ApgService
|
2013-01-16 14:31:16 +01:00
|
|
|
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(this,
|
2012-11-16 02:34:21 +01:00
|
|
|
R.string.progress_saving, ProgressDialog.STYLE_HORIZONTAL) {
|
2012-04-25 15:10:12 +02:00
|
|
|
public void handleMessage(Message message) {
|
|
|
|
|
// handle messages by standard ApgHandler first
|
|
|
|
|
super.handleMessage(message);
|
|
|
|
|
|
2013-01-16 14:31:16 +01:00
|
|
|
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
|
2012-12-12 19:14:09 +01:00
|
|
|
Intent data = new Intent();
|
|
|
|
|
data.putExtra(RESULT_EXTRA_MASTER_KEY_ID, getMasterKeyId());
|
|
|
|
|
ArrayList<String> userIds = null;
|
|
|
|
|
try {
|
|
|
|
|
userIds = getUserIds(mUserIdsView);
|
2013-01-16 14:31:16 +01:00
|
|
|
} catch (PgpGeneralException e) {
|
2012-12-12 19:14:09 +01:00
|
|
|
Log.e(Constants.TAG, "exception while getting user ids", e);
|
|
|
|
|
}
|
|
|
|
|
data.putExtra(RESULT_EXTRA_USER_ID, userIds.get(0));
|
|
|
|
|
setResult(RESULT_OK, data);
|
2012-04-25 15:10:12 +02:00
|
|
|
finish();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Create a new Messenger for the communication back
|
|
|
|
|
Messenger messenger = new Messenger(saveHandler);
|
2013-01-16 14:31:16 +01:00
|
|
|
intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
|
2012-04-25 15:10:12 +02:00
|
|
|
|
2012-09-10 18:22:47 +02:00
|
|
|
saveHandler.showProgressDialog(this);
|
2012-04-20 12:12:07 +02:00
|
|
|
|
2012-04-25 15:10:12 +02:00
|
|
|
// start service with intent
|
|
|
|
|
startService(intent);
|
2013-01-16 14:31:16 +01:00
|
|
|
} catch (PgpMain.PgpGeneralException e) {
|
2012-04-25 15:10:12 +02:00
|
|
|
Toast.makeText(this, getString(R.string.errorMessage, e.getMessage()),
|
|
|
|
|
Toast.LENGTH_SHORT).show();
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-04-20 12:12:07 +02:00
|
|
|
|
2012-12-12 19:14:09 +01:00
|
|
|
private void cancelClicked() {
|
|
|
|
|
setResult(RESULT_CANCELED);
|
|
|
|
|
finish();
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-25 15:10:12 +02:00
|
|
|
/**
|
|
|
|
|
* Returns user ids from the SectionView
|
|
|
|
|
*
|
|
|
|
|
* @param userIdsView
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2012-09-20 17:13:45 +02:00
|
|
|
private ArrayList<String> getUserIds(SectionView userIdsView)
|
2013-01-16 14:31:16 +01:00
|
|
|
throws PgpMain.PgpGeneralException {
|
2012-09-13 18:24:10 +02:00
|
|
|
ArrayList<String> userIds = new ArrayList<String>();
|
2010-04-06 19:54:51 +00:00
|
|
|
|
2012-04-20 12:12:07 +02:00
|
|
|
ViewGroup userIdEditors = userIdsView.getEditors();
|
|
|
|
|
|
|
|
|
|
boolean gotMainUserId = false;
|
|
|
|
|
for (int i = 0; i < userIdEditors.getChildCount(); ++i) {
|
|
|
|
|
UserIdEditor editor = (UserIdEditor) userIdEditors.getChildAt(i);
|
|
|
|
|
String userId = null;
|
|
|
|
|
try {
|
|
|
|
|
userId = editor.getValue();
|
|
|
|
|
} catch (UserIdEditor.NoNameException e) {
|
2013-01-16 14:31:16 +01:00
|
|
|
throw new PgpMain.PgpGeneralException(
|
2012-09-20 17:13:45 +02:00
|
|
|
this.getString(R.string.error_userIdNeedsAName));
|
2012-04-20 12:12:07 +02:00
|
|
|
} catch (UserIdEditor.NoEmailException e) {
|
2013-01-16 14:31:16 +01:00
|
|
|
throw new PgpMain.PgpGeneralException(
|
2012-04-25 15:10:12 +02:00
|
|
|
this.getString(R.string.error_userIdNeedsAnEmailAddress));
|
2012-04-20 12:12:07 +02:00
|
|
|
} catch (UserIdEditor.InvalidEmailException e) {
|
2013-01-16 14:31:16 +01:00
|
|
|
throw new PgpMain.PgpGeneralException(e.getMessage());
|
2012-04-20 12:12:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (userId.equals("")) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (editor.isMainUserId()) {
|
2012-09-13 18:24:10 +02:00
|
|
|
userIds.add(0, userId);
|
2012-04-20 12:12:07 +02:00
|
|
|
gotMainUserId = true;
|
|
|
|
|
} else {
|
|
|
|
|
userIds.add(userId);
|
2010-04-06 19:54:51 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-20 12:12:07 +02:00
|
|
|
if (userIds.size() == 0) {
|
2013-01-16 14:31:16 +01:00
|
|
|
throw new PgpMain.PgpGeneralException(getString(R.string.error_keyNeedsAUserId));
|
2012-04-20 12:12:07 +02:00
|
|
|
}
|
2010-04-06 19:54:51 +00:00
|
|
|
|
2012-04-20 12:12:07 +02:00
|
|
|
if (!gotMainUserId) {
|
2013-01-16 14:31:16 +01:00
|
|
|
throw new PgpMain.PgpGeneralException(
|
2012-09-20 17:13:45 +02:00
|
|
|
getString(R.string.error_mainUserIdMustNotBeEmpty));
|
2010-04-06 19:54:51 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-20 12:12:07 +02:00
|
|
|
return userIds;
|
2010-04-06 19:54:51 +00:00
|
|
|
}
|
|
|
|
|
|
2012-04-25 15:10:12 +02:00
|
|
|
/**
|
|
|
|
|
* Returns keys from the SectionView
|
|
|
|
|
*
|
|
|
|
|
* @param keysView
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2012-09-20 17:13:45 +02:00
|
|
|
private ArrayList<PGPSecretKey> getKeys(SectionView keysView)
|
2013-01-16 14:31:16 +01:00
|
|
|
throws PgpMain.PgpGeneralException {
|
2012-09-13 18:24:10 +02:00
|
|
|
ArrayList<PGPSecretKey> keys = new ArrayList<PGPSecretKey>();
|
2010-04-06 19:54:51 +00:00
|
|
|
|
2012-04-20 12:12:07 +02:00
|
|
|
ViewGroup keyEditors = keysView.getEditors();
|
major restructuring, moving dialog, message, menu, option menu, task, type IDs into Id in a similar structure as the generated R, also introducing a BaseActivity class that almost all activities derive from, which generates some common dialogs, handles the progress update, thread management, and thread communication
also adding first draft of encrypt file activity, not very functional yet
2010-04-19 02:12:13 +00:00
|
|
|
|
2012-04-20 12:12:07 +02:00
|
|
|
if (keyEditors.getChildCount() == 0) {
|
2013-01-16 14:31:16 +01:00
|
|
|
throw new PgpMain.PgpGeneralException(getString(R.string.error_keyNeedsMasterKey));
|
2012-04-20 12:12:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < keyEditors.getChildCount(); ++i) {
|
|
|
|
|
KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i);
|
|
|
|
|
keys.add(editor.getValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return keys;
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-25 15:10:12 +02:00
|
|
|
/**
|
|
|
|
|
* Returns usage selections of keys from the SectionView
|
|
|
|
|
*
|
|
|
|
|
* @param keysView
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
2012-09-20 17:13:45 +02:00
|
|
|
private ArrayList<Integer> getKeysUsages(SectionView keysView)
|
2013-01-16 14:31:16 +01:00
|
|
|
throws PgpMain.PgpGeneralException {
|
2012-09-13 18:24:10 +02:00
|
|
|
ArrayList<Integer> getKeysUsages = new ArrayList<Integer>();
|
2012-04-20 12:12:07 +02:00
|
|
|
|
|
|
|
|
ViewGroup keyEditors = keysView.getEditors();
|
|
|
|
|
|
|
|
|
|
if (keyEditors.getChildCount() == 0) {
|
2013-01-16 14:31:16 +01:00
|
|
|
throw new PgpMain.PgpGeneralException(getString(R.string.error_keyNeedsMasterKey));
|
major restructuring, moving dialog, message, menu, option menu, task, type IDs into Id in a similar structure as the generated R, also introducing a BaseActivity class that almost all activities derive from, which generates some common dialogs, handles the progress update, thread management, and thread communication
also adding first draft of encrypt file activity, not very functional yet
2010-04-19 02:12:13 +00:00
|
|
|
}
|
2012-04-20 12:12:07 +02:00
|
|
|
|
|
|
|
|
for (int i = 0; i < keyEditors.getChildCount(); ++i) {
|
|
|
|
|
KeyEditor editor = (KeyEditor) keyEditors.getChildAt(i);
|
|
|
|
|
getKeysUsages.add(editor.getUsage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return getKeysUsages;
|
2010-04-06 19:54:51 +00:00
|
|
|
}
|
2010-07-23 12:57:02 +00:00
|
|
|
|
|
|
|
|
private void updatePassPhraseButtonText() {
|
2012-04-13 16:54:50 +02:00
|
|
|
mChangePassPhrase.setText(isPassphraseSet() ? R.string.btn_changePassPhrase
|
2012-03-09 16:27:29 +01:00
|
|
|
: R.string.btn_setPassPhrase);
|
2010-07-23 12:57:02 +00:00
|
|
|
}
|
2012-03-09 11:08:22 +01:00
|
|
|
}
|