Merge branch 'master' into ditch-appmsg
Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyActivityOld.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListActivity.java
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Patterns;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ContactHelper;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class CreateKeyActivity extends ActionBarActivity {
|
||||
|
||||
AutoCompleteTextView mNameEdit;
|
||||
AutoCompleteTextView mEmailEdit;
|
||||
EditText mPassphraseEdit;
|
||||
Button mCreateButton;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.create_key_activity);
|
||||
|
||||
mNameEdit = (AutoCompleteTextView) findViewById(R.id.name);
|
||||
mEmailEdit = (AutoCompleteTextView) findViewById(R.id.email);
|
||||
mPassphraseEdit = (EditText) findViewById(R.id.passphrase);
|
||||
mCreateButton = (Button) findViewById(R.id.create_key_button);
|
||||
|
||||
mEmailEdit.setThreshold(1); // Start working from first character
|
||||
mEmailEdit.setAdapter(
|
||||
new ArrayAdapter<String>
|
||||
(this, android.R.layout.simple_spinner_dropdown_item,
|
||||
ContactHelper.getPossibleUserEmails(this)
|
||||
)
|
||||
);
|
||||
mEmailEdit.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
String email = editable.toString();
|
||||
if (email.length() > 0) {
|
||||
Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email);
|
||||
if (emailMatcher.matches()) {
|
||||
mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0,
|
||||
R.drawable.uid_mail_ok, 0);
|
||||
} else {
|
||||
mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0,
|
||||
R.drawable.uid_mail_bad, 0);
|
||||
}
|
||||
} else {
|
||||
// remove drawable if email is empty
|
||||
mEmailEdit.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mNameEdit.setThreshold(1); // Start working from first character
|
||||
mNameEdit.setAdapter(
|
||||
new ArrayAdapter<String>
|
||||
(this, android.R.layout.simple_spinner_dropdown_item,
|
||||
ContactHelper.getPossibleUserNames(this)
|
||||
)
|
||||
);
|
||||
|
||||
mCreateButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createKeyCheck();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void createKeyCheck() {
|
||||
if (isEditTextNotEmpty(this, mNameEdit)
|
||||
&& isEditTextNotEmpty(this, mEmailEdit)
|
||||
&& isEditTextNotEmpty(this, mPassphraseEdit)) {
|
||||
createKey();
|
||||
}
|
||||
}
|
||||
|
||||
private void createKey() {
|
||||
Intent intent = new Intent(this, KeychainIntentService.class);
|
||||
intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING);
|
||||
|
||||
// Message is received after importing is done in KeychainIntentService
|
||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
||||
this,
|
||||
getString(R.string.progress_importing),
|
||||
ProgressDialog.STYLE_HORIZONTAL) {
|
||||
public void handleMessage(Message message) {
|
||||
// handle messages by standard KeychainIntentServiceHandler first
|
||||
super.handleMessage(message);
|
||||
|
||||
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
|
||||
CreateKeyActivity.this.setResult(RESULT_OK);
|
||||
CreateKeyActivity.this.finish();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// fill values for this action
|
||||
Bundle data = new Bundle();
|
||||
|
||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.CERTIFY_OTHER, null));
|
||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.SIGN_DATA, null));
|
||||
parcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(Constants.choice.algorithm.rsa, 4096, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, null));
|
||||
String userId = mNameEdit.getText().toString() + " <" + mEmailEdit.getText().toString() + ">";
|
||||
parcel.mAddUserIds.add(userId);
|
||||
parcel.mNewPassphrase = mPassphraseEdit.getText().toString();
|
||||
|
||||
// get selected key entries
|
||||
data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, parcel);
|
||||
|
||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||
|
||||
// Create a new Messenger for the communication back
|
||||
Messenger messenger = new Messenger(saveHandler);
|
||||
intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
|
||||
|
||||
saveHandler.showProgressDialog(this);
|
||||
|
||||
startService(intent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if text of given EditText is not empty. If it is empty an error is
|
||||
* set and the EditText gets the focus.
|
||||
*
|
||||
* @param context
|
||||
* @param editText
|
||||
* @return true if EditText is not empty
|
||||
*/
|
||||
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
||||
boolean output = true;
|
||||
if (editText.getText().toString().length() == 0) {
|
||||
editText.setError("empty!");
|
||||
editText.requestFocus();
|
||||
output = false;
|
||||
} else {
|
||||
editText.setError(null);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
@@ -54,12 +54,15 @@ import org.sufficientlysecure.keychain.ui.adapter.SubkeysAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.SubkeysAddedAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAddedAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.ChangeExpiryDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.EditSubkeyDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
|
||||
public class EditKeyFragment extends LoaderFragment implements
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
@@ -214,10 +217,18 @@ public class EditKeyFragment extends LoaderFragment implements
|
||||
mUserIdsAddedAdapter = new UserIdsAddedAdapter(getActivity(), mUserIdsAddedData);
|
||||
mUserIdsAddedList.setAdapter(mUserIdsAddedAdapter);
|
||||
|
||||
mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0);
|
||||
mSubkeysAdapter = new SubkeysAdapter(getActivity(), null, 0, mSaveKeyringParcel);
|
||||
mSubkeysList.setAdapter(mSubkeysAdapter);
|
||||
|
||||
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.addSubKeys);
|
||||
mSubkeysList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
long keyId = mSubkeysAdapter.getKeyId(position);
|
||||
editSubkey(keyId);
|
||||
}
|
||||
});
|
||||
|
||||
mSubkeysAddedAdapter = new SubkeysAddedAdapter(getActivity(), mSaveKeyringParcel.mAddSubKeys);
|
||||
mSubkeysAddedList.setAdapter(mSubkeysAddedAdapter);
|
||||
|
||||
// Prepare the loaders. Either re-connect with an existing ones,
|
||||
@@ -287,7 +298,7 @@ public class EditKeyFragment extends LoaderFragment implements
|
||||
Bundle data = message.getData();
|
||||
|
||||
// cache new returned passphrase!
|
||||
mSaveKeyringParcel.newPassphrase = data
|
||||
mSaveKeyringParcel.mNewPassphrase = data
|
||||
.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE);
|
||||
}
|
||||
}
|
||||
@@ -309,19 +320,19 @@ public class EditKeyFragment extends LoaderFragment implements
|
||||
switch (message.what) {
|
||||
case EditUserIdDialogFragment.MESSAGE_CHANGE_PRIMARY_USER_ID:
|
||||
// toggle
|
||||
if (mSaveKeyringParcel.changePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.changePrimaryUserId.equals(userId)) {
|
||||
mSaveKeyringParcel.changePrimaryUserId = null;
|
||||
if (mSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId)) {
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = null;
|
||||
} else {
|
||||
mSaveKeyringParcel.changePrimaryUserId = userId;
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = userId;
|
||||
}
|
||||
break;
|
||||
case EditUserIdDialogFragment.MESSAGE_REVOKE:
|
||||
// toggle
|
||||
if (mSaveKeyringParcel.revokeUserIds.contains(userId)) {
|
||||
mSaveKeyringParcel.revokeUserIds.remove(userId);
|
||||
if (mSaveKeyringParcel.mRevokeUserIds.contains(userId)) {
|
||||
mSaveKeyringParcel.mRevokeUserIds.remove(userId);
|
||||
} else {
|
||||
mSaveKeyringParcel.revokeUserIds.add(userId);
|
||||
mSaveKeyringParcel.mRevokeUserIds.add(userId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -342,6 +353,72 @@ public class EditKeyFragment extends LoaderFragment implements
|
||||
});
|
||||
}
|
||||
|
||||
private void editSubkey(final long keyId) {
|
||||
Handler returnHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case EditSubkeyDialogFragment.MESSAGE_CHANGE_EXPIRY:
|
||||
editSubkeyExpiry(keyId);
|
||||
break;
|
||||
case EditSubkeyDialogFragment.MESSAGE_REVOKE:
|
||||
// toggle
|
||||
if (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId)) {
|
||||
mSaveKeyringParcel.mRevokeSubKeys.remove(keyId);
|
||||
} else {
|
||||
mSaveKeyringParcel.mRevokeSubKeys.add(keyId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
|
||||
}
|
||||
};
|
||||
|
||||
// Create a new Messenger for the communication back
|
||||
final Messenger messenger = new Messenger(returnHandler);
|
||||
|
||||
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
|
||||
public void run() {
|
||||
EditSubkeyDialogFragment dialogFragment =
|
||||
EditSubkeyDialogFragment.newInstance(messenger);
|
||||
|
||||
dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyDialog");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void editSubkeyExpiry(final long keyId) {
|
||||
Handler returnHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case ChangeExpiryDialogFragment.MESSAGE_NEW_EXPIRY_DATE:
|
||||
// toggle
|
||||
// if (mSaveKeyringParcel.changePrimaryUserId != null
|
||||
// && mSaveKeyringParcel.changePrimaryUserId.equals(userId)) {
|
||||
// mSaveKeyringParcel.changePrimaryUserId = null;
|
||||
// } else {
|
||||
// mSaveKeyringParcel.changePrimaryUserId = userId;
|
||||
// }
|
||||
break;
|
||||
}
|
||||
getLoaderManager().getLoader(LOADER_ID_SUBKEYS).forceLoad();
|
||||
}
|
||||
};
|
||||
|
||||
// Create a new Messenger for the communication back
|
||||
final Messenger messenger = new Messenger(returnHandler);
|
||||
|
||||
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
|
||||
public void run() {
|
||||
ChangeExpiryDialogFragment dialogFragment =
|
||||
ChangeExpiryDialogFragment.newInstance(messenger, new Date(), new Date());
|
||||
|
||||
dialogFragment.show(getActivity().getSupportFragmentManager(), "editSubkeyExpiryDialog");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addUserId() {
|
||||
mUserIdsAddedAdapter.add(new UserIdsAddedAdapter.UserIdModel());
|
||||
}
|
||||
@@ -373,10 +450,11 @@ public class EditKeyFragment extends LoaderFragment implements
|
||||
}
|
||||
|
||||
private void save(String passphrase) {
|
||||
Log.d(Constants.TAG, "add userids to parcel: " + mUserIdsAddedAdapter.getDataAsStringList());
|
||||
Log.d(Constants.TAG, "mSaveKeyringParcel.newPassphrase: " + mSaveKeyringParcel.newPassphrase);
|
||||
mSaveKeyringParcel.mAddUserIds = mUserIdsAddedAdapter.getDataAsStringList();
|
||||
|
||||
mSaveKeyringParcel.addUserIds = mUserIdsAddedAdapter.getDataAsStringList();
|
||||
Log.d(Constants.TAG, "mSaveKeyringParcel.mAddUserIds: " + mSaveKeyringParcel.mAddUserIds);
|
||||
Log.d(Constants.TAG, "mSaveKeyringParcel.mNewPassphrase: " + mSaveKeyringParcel.mNewPassphrase);
|
||||
Log.d(Constants.TAG, "mSaveKeyringParcel.mRevokeUserIds: " + mSaveKeyringParcel.mRevokeUserIds);
|
||||
|
||||
// Message is received after importing is done in KeychainIntentService
|
||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
||||
@@ -432,4 +510,4 @@ public class EditKeyFragment extends LoaderFragment implements
|
||||
// start service with intent
|
||||
getActivity().startService(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ public class EncryptAsymmetricFragment extends Fragment {
|
||||
String[] userId;
|
||||
try {
|
||||
userId = mProviderHelper.getCachedPublicKeyRing(
|
||||
KeyRings.buildUnifiedKeyRingUri(mSecretKeyId)).getSplitPrimaryUserId();
|
||||
KeyRings.buildUnifiedKeyRingUri(mSecretKeyId)).getSplitPrimaryUserIdWithFallback();
|
||||
} catch (PgpGeneralException e) {
|
||||
userId = null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
|
||||
public class FirstTimeActivity extends ActionBarActivity {
|
||||
|
||||
Button mCreateKey;
|
||||
Button mImportKey;
|
||||
Button mSkipSetup;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
setContentView(R.layout.first_time_activity);
|
||||
|
||||
mCreateKey = (Button) findViewById(R.id.first_time_create_key);
|
||||
mImportKey = (Button) findViewById(R.id.first_time_import_key);
|
||||
mSkipSetup = (Button) findViewById(R.id.first_time_cancel);
|
||||
|
||||
mSkipSetup.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finishSetup();
|
||||
}
|
||||
});
|
||||
|
||||
mImportKey.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(FirstTimeActivity.this, ImportKeysActivity.class);
|
||||
intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
|
||||
startActivityForResult(intent, 1);
|
||||
}
|
||||
});
|
||||
|
||||
mCreateKey.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(FirstTimeActivity.this, CreateKeyActivity.class);
|
||||
startActivityForResult(intent, 1);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode == RESULT_OK) {
|
||||
finishSetup();
|
||||
}
|
||||
}
|
||||
|
||||
private void finishSetup() {
|
||||
Preferences prefs = Preferences.getPreferences(this);
|
||||
prefs.setFirstTime(false);
|
||||
Intent intent = new Intent(FirstTimeActivity.this, KeyListActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@@ -17,25 +17,17 @@
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Constants.choice.algorithm;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ExportHelper;
|
||||
import org.sufficientlysecure.keychain.helper.Preferences;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.SubkeyAdd;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Notify;
|
||||
|
||||
@@ -49,6 +41,14 @@ public class KeyListActivity extends DrawerActivity {
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// if this is the first time show first time activity
|
||||
Preferences prefs = Preferences.getPreferences(this);
|
||||
if (prefs.isFirstTime()) {
|
||||
startActivity(new Intent(this, FirstTimeActivity.class));
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
mExportHelper = new ExportHelper(this);
|
||||
|
||||
setContentView(R.layout.key_list_activity);
|
||||
@@ -62,9 +62,10 @@ public class KeyListActivity extends DrawerActivity {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
getMenuInflater().inflate(R.menu.key_list, menu);
|
||||
|
||||
if(Constants.DEBUG) {
|
||||
if (Constants.DEBUG) {
|
||||
menu.findItem(R.id.menu_key_list_debug_read).setVisible(true);
|
||||
menu.findItem(R.id.menu_key_list_debug_write).setVisible(true);
|
||||
menu.findItem(R.id.menu_key_list_debug_first_time).setVisible(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -81,10 +82,6 @@ public class KeyListActivity extends DrawerActivity {
|
||||
createKey();
|
||||
return true;
|
||||
|
||||
case R.id.menu_key_list_create_expert:
|
||||
createKeyExpert();
|
||||
return true;
|
||||
|
||||
case R.id.menu_key_list_export:
|
||||
mExportHelper.showExportKeysDialog(null, Constants.Path.APP_DIR_FILE, true);
|
||||
return true;
|
||||
@@ -94,7 +91,7 @@ public class KeyListActivity extends DrawerActivity {
|
||||
KeychainDatabase.debugRead(this);
|
||||
Notify.showNotify(this, "Restored Notify.Style backup", Notify.Style.INFO);
|
||||
getContentResolver().notifyChange(KeychainContract.KeyRings.CONTENT_URI, null);
|
||||
} catch(IOException e) {
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "IO Error", e);
|
||||
Notify.showNotify(this, "IO Notify.Style: " + e.getMessage(), Notify.Style.ERROR);
|
||||
}
|
||||
@@ -110,6 +107,12 @@ public class KeyListActivity extends DrawerActivity {
|
||||
}
|
||||
return true;
|
||||
|
||||
case R.id.menu_key_list_debug_first_time:
|
||||
Intent intent = new Intent(this, FirstTimeActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
return true;
|
||||
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@@ -121,50 +124,8 @@ public class KeyListActivity extends DrawerActivity {
|
||||
}
|
||||
|
||||
private void createKey() {
|
||||
Intent intent = new Intent(this, WizardActivity.class);
|
||||
// intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
|
||||
// intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true);
|
||||
// intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view
|
||||
startActivityForResult(intent, 0);
|
||||
Intent intent = new Intent(this, CreateKeyActivity.class);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void createKeyExpert() {
|
||||
Intent intent = new Intent(this, KeychainIntentService.class);
|
||||
intent.setAction(KeychainIntentService.ACTION_SAVE_KEYRING);
|
||||
|
||||
// Message is received after importing is done in KeychainIntentService
|
||||
KeychainIntentServiceHandler saveHandler = new KeychainIntentServiceHandler(
|
||||
this,
|
||||
getString(R.string.progress_importing),
|
||||
ProgressDialog.STYLE_HORIZONTAL) {
|
||||
public void handleMessage(Message message) {
|
||||
// handle messages by standard KeychainIntentServiceHandler first
|
||||
super.handleMessage(message);
|
||||
Bundle data = message.getData();
|
||||
// OtherHelper.logDebugBundle(data, "message reply");
|
||||
}
|
||||
};
|
||||
|
||||
// fill values for this action
|
||||
Bundle data = new Bundle();
|
||||
|
||||
SaveKeyringParcel parcel = new SaveKeyringParcel();
|
||||
parcel.addSubKeys.add(new SubkeyAdd(algorithm.rsa, 1024, KeyFlags.CERTIFY_OTHER, null));
|
||||
parcel.addSubKeys.add(new SubkeyAdd(algorithm.rsa, 1024, KeyFlags.SIGN_DATA, null));
|
||||
parcel.addUserIds.add("swagerinho");
|
||||
parcel.newPassphrase = "swag";
|
||||
|
||||
// get selected key entries
|
||||
data.putParcelable(KeychainIntentService.SAVE_KEYRING_PARCEL, parcel);
|
||||
|
||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||
|
||||
// Create a new Messenger for the communication back
|
||||
Messenger messenger = new Messenger(saveHandler);
|
||||
intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
|
||||
|
||||
saveHandler.showProgressDialog(this);
|
||||
|
||||
startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class LogDisplayFragment extends ListFragment implements OnTouchListener {
|
||||
|
||||
@@ -135,7 +136,7 @@ public class LogDisplayFragment extends ListFragment implements OnTouchListener
|
||||
private LayoutInflater mInflater;
|
||||
private int dipFactor;
|
||||
|
||||
public LogAdapter(Context context, ArrayList<LogEntryParcel> log, LogLevel level) {
|
||||
public LogAdapter(Context context, OperationResultParcel.OperationLog log, LogLevel level) {
|
||||
super(context, R.layout.log_display_item);
|
||||
mInflater = LayoutInflater.from(getContext());
|
||||
dipFactor = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||
|
||||
@@ -121,6 +121,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
initializeForceV3Signatures(
|
||||
(CheckBoxPreference) findPreference(Constants.Pref.FORCE_V3_SIGNATURES));
|
||||
|
||||
initializeConcealPgpApplication(
|
||||
(CheckBoxPreference) findPreference(Constants.Pref.CONCEAL_PGP_APPLICATION));
|
||||
|
||||
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
||||
// Load the legacy preferences headers
|
||||
addPreferencesFromResource(R.xml.preference_headers_legacy);
|
||||
@@ -264,6 +267,9 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
|
||||
initializeForceV3Signatures(
|
||||
(CheckBoxPreference) findPreference(Constants.Pref.FORCE_V3_SIGNATURES));
|
||||
|
||||
initializeConcealPgpApplication(
|
||||
(CheckBoxPreference) findPreference(Constants.Pref.CONCEAL_PGP_APPLICATION));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,4 +402,15 @@ public class PreferencesActivity extends PreferenceActivity {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void initializeConcealPgpApplication(final CheckBoxPreference mConcealPgpApplication) {
|
||||
mConcealPgpApplication.setChecked(sPreferences.getConcealPgpApplication());
|
||||
mConcealPgpApplication.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mConcealPgpApplication.setChecked((Boolean) newValue);
|
||||
sPreferences.setConcealPgpApplication((Boolean) newValue);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,8 +149,8 @@ public class ViewCertActivity extends ActionBarActivity
|
||||
providerHelper.getWrappedPublicKeyRing(sig.getKeyId());
|
||||
|
||||
try {
|
||||
sig.init(signerRing.getSubkey());
|
||||
if (sig.verifySignature(signeeRing.getSubkey(), signeeUid)) {
|
||||
sig.init(signerRing.getPublicKey());
|
||||
if (sig.verifySignature(signeeRing.getPublicKey(), signeeUid)) {
|
||||
mStatus.setText(R.string.cert_verify_ok);
|
||||
mStatus.setTextColor(getResources().getColor(R.color.result_green));
|
||||
} else {
|
||||
|
||||
@@ -1,466 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Patterns;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.htmltextview.HtmlTextView;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.ContactHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
|
||||
public class WizardActivity extends ActionBarActivity {
|
||||
|
||||
private State mCurrentState;
|
||||
|
||||
// values for mCurrentScreen
|
||||
private enum State {
|
||||
START, CREATE_KEY, IMPORT_KEY, K9
|
||||
}
|
||||
|
||||
public static final int REQUEST_CODE_IMPORT = 0x00007703;
|
||||
|
||||
Button mBackButton;
|
||||
Button mNextButton;
|
||||
StartFragment mStartFragment;
|
||||
CreateKeyFragment mCreateKeyFragment;
|
||||
K9Fragment mK9Fragment;
|
||||
|
||||
private static final String K9_PACKAGE = "com.fsck.k9";
|
||||
// private static final String K9_MARKET_INTENT_URI_BASE = "market://details?id=%s";
|
||||
// private static final Intent K9_MARKET_INTENT = new Intent(Intent.ACTION_VIEW, Uri.parse(
|
||||
// String.format(K9_MARKET_INTENT_URI_BASE, K9_PACKAGE)));
|
||||
private static final Intent K9_MARKET_INTENT = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/k9mail/k-9/releases/tag/4.904"));
|
||||
|
||||
LinearLayout mProgressLayout;
|
||||
View mProgressLine;
|
||||
ProgressBar mProgressBar;
|
||||
ImageView mProgressImage;
|
||||
TextView mProgressText;
|
||||
|
||||
/**
|
||||
* Checks if text of given EditText is not empty. If it is empty an error is
|
||||
* set and the EditText gets the focus.
|
||||
*
|
||||
* @param context
|
||||
* @param editText
|
||||
* @return true if EditText is not empty
|
||||
*/
|
||||
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
||||
boolean output = true;
|
||||
if (editText.getText().toString().length() == 0) {
|
||||
editText.setError("empty!");
|
||||
editText.requestFocus();
|
||||
output = false;
|
||||
} else {
|
||||
editText.setError(null);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public static class StartFragment extends Fragment {
|
||||
public static StartFragment newInstance() {
|
||||
StartFragment myFragment = new StartFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
myFragment.setArguments(args);
|
||||
|
||||
return myFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.wizard_start_fragment,
|
||||
container, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CreateKeyFragment extends Fragment {
|
||||
public static CreateKeyFragment newInstance() {
|
||||
CreateKeyFragment myFragment = new CreateKeyFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
myFragment.setArguments(args);
|
||||
|
||||
return myFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.wizard_create_key_fragment,
|
||||
container, false);
|
||||
|
||||
final AutoCompleteTextView emailView = (AutoCompleteTextView) view.findViewById(R.id.email);
|
||||
emailView.setThreshold(1); // Start working from first character
|
||||
emailView.setAdapter(
|
||||
new ArrayAdapter<String>
|
||||
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
|
||||
ContactHelper.getPossibleUserEmails(getActivity())
|
||||
)
|
||||
);
|
||||
emailView.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
String email = editable.toString();
|
||||
if (email.length() > 0) {
|
||||
Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email);
|
||||
if (emailMatcher.matches()) {
|
||||
emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0,
|
||||
R.drawable.uid_mail_ok, 0);
|
||||
} else {
|
||||
emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0,
|
||||
R.drawable.uid_mail_bad, 0);
|
||||
}
|
||||
} else {
|
||||
// remove drawable if email is empty
|
||||
emailView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
});
|
||||
final AutoCompleteTextView nameView = (AutoCompleteTextView) view.findViewById(R.id.name);
|
||||
nameView.setThreshold(1); // Start working from first character
|
||||
nameView.setAdapter(
|
||||
new ArrayAdapter<String>
|
||||
(getActivity(), android.R.layout.simple_spinner_dropdown_item,
|
||||
ContactHelper.getPossibleUserNames(getActivity())
|
||||
)
|
||||
);
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
public static class K9Fragment extends Fragment {
|
||||
public static K9Fragment newInstance() {
|
||||
K9Fragment myFragment = new K9Fragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
myFragment.setArguments(args);
|
||||
|
||||
return myFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.wizard_k9_fragment,
|
||||
container, false);
|
||||
|
||||
HtmlTextView text = (HtmlTextView) v
|
||||
.findViewById(R.id.wizard_k9_text);
|
||||
text.setHtmlFromString("Install K9. It's good for you! Here is a screenhot how to enable OK in K9: (TODO)", true);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads new fragment
|
||||
*
|
||||
* @param fragment
|
||||
*/
|
||||
private void loadFragment(Fragment fragment) {
|
||||
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||
FragmentTransaction fragmentTransaction = fragmentManager
|
||||
.beginTransaction();
|
||||
fragmentTransaction.replace(R.id.wizard_container,
|
||||
fragment);
|
||||
fragmentTransaction.commit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate View and initialize fragments for this Activity
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.wizard_activity);
|
||||
mBackButton = (Button) findViewById(R.id.wizard_back);
|
||||
mNextButton = (Button) findViewById(R.id.wizard_next);
|
||||
|
||||
// progress layout
|
||||
mProgressLayout = (LinearLayout) findViewById(R.id.wizard_progress);
|
||||
mProgressLine = findViewById(R.id.wizard_progress_line);
|
||||
mProgressBar = (ProgressBar) findViewById(R.id.wizard_progress_progressbar);
|
||||
mProgressImage = (ImageView) findViewById(R.id.wizard_progress_image);
|
||||
mProgressText = (TextView) findViewById(R.id.wizard_progress_text);
|
||||
|
||||
changeToState(State.START);
|
||||
}
|
||||
|
||||
private enum ProgressState {
|
||||
WORKING, ENABLED, DISABLED, ERROR
|
||||
}
|
||||
|
||||
private void showProgress(ProgressState state, String text) {
|
||||
switch (state) {
|
||||
case WORKING:
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
mProgressImage.setVisibility(View.GONE);
|
||||
break;
|
||||
case ENABLED:
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mProgressImage.setVisibility(View.VISIBLE);
|
||||
// mProgressImage.setImageDrawable(getResources().getDrawable(
|
||||
// R.drawable.status_enabled));
|
||||
break;
|
||||
case DISABLED:
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mProgressImage.setVisibility(View.VISIBLE);
|
||||
// mProgressImage.setImageDrawable(getResources().getDrawable(
|
||||
// R.drawable.status_disabled));
|
||||
break;
|
||||
case ERROR:
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mProgressImage.setVisibility(View.VISIBLE);
|
||||
// mProgressImage.setImageDrawable(getResources().getDrawable(
|
||||
// R.drawable.status_fail));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mProgressText.setText(text);
|
||||
|
||||
mProgressLine.setVisibility(View.VISIBLE);
|
||||
mProgressLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void hideProgress() {
|
||||
mProgressLine.setVisibility(View.GONE);
|
||||
mProgressLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void nextOnClick(View view) {
|
||||
// close keyboard
|
||||
if (getCurrentFocus() != null) {
|
||||
InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
inputManager.hideSoftInputFromWindow(getCurrentFocus()
|
||||
.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
|
||||
}
|
||||
|
||||
switch (mCurrentState) {
|
||||
case START: {
|
||||
RadioGroup radioGroup = (RadioGroup) findViewById(R.id.wizard_start_radio_group);
|
||||
int selectedId = radioGroup.getCheckedRadioButtonId();
|
||||
switch (selectedId) {
|
||||
case R.id.wizard_start_new_key: {
|
||||
changeToState(State.CREATE_KEY);
|
||||
break;
|
||||
}
|
||||
case R.id.wizard_start_import: {
|
||||
changeToState(State.IMPORT_KEY);
|
||||
break;
|
||||
}
|
||||
case R.id.wizard_start_skip: {
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mBackButton.setText(R.string.btn_back);
|
||||
break;
|
||||
}
|
||||
case CREATE_KEY:
|
||||
EditText nameEdit = (EditText) findViewById(R.id.name);
|
||||
EditText emailEdit = (EditText) findViewById(R.id.email);
|
||||
EditText passphraseEdit = (EditText) findViewById(R.id.passphrase);
|
||||
|
||||
if (isEditTextNotEmpty(this, nameEdit)
|
||||
&& isEditTextNotEmpty(this, emailEdit)
|
||||
&& isEditTextNotEmpty(this, passphraseEdit)) {
|
||||
|
||||
// SaveKeyringParcel newKey = new SaveKeyringParcel();
|
||||
// newKey.addUserIds.add(nameEdit.getText().toString() + " <"
|
||||
// + emailEdit.getText().toString() + ">");
|
||||
|
||||
|
||||
AsyncTask<String, Boolean, Boolean> generateTask = new AsyncTask<String, Boolean, Boolean>() {
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
|
||||
showProgress(ProgressState.WORKING, "generating key...");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(String... params) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean result) {
|
||||
super.onPostExecute(result);
|
||||
|
||||
if (result) {
|
||||
showProgress(ProgressState.ENABLED, "key generated successfully!");
|
||||
|
||||
changeToState(State.K9);
|
||||
} else {
|
||||
showProgress(ProgressState.ERROR, "error in key gen");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
generateTask.execute("");
|
||||
}
|
||||
break;
|
||||
case K9: {
|
||||
RadioGroup radioGroup = (RadioGroup) findViewById(R.id.wizard_k9_radio_group);
|
||||
int selectedId = radioGroup.getCheckedRadioButtonId();
|
||||
switch (selectedId) {
|
||||
case R.id.wizard_k9_install: {
|
||||
try {
|
||||
startActivity(K9_MARKET_INTENT);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.e(Constants.TAG, "Activity not found for: " + K9_MARKET_INTENT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case R.id.wizard_k9_skip: {
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_IMPORT: {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
// imported now...
|
||||
changeToState(State.K9);
|
||||
} else {
|
||||
// back to start
|
||||
changeToState(State.START);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void backOnClick(View view) {
|
||||
switch (mCurrentState) {
|
||||
case START:
|
||||
finish();
|
||||
break;
|
||||
case CREATE_KEY:
|
||||
changeToState(State.START);
|
||||
break;
|
||||
case IMPORT_KEY:
|
||||
changeToState(State.START);
|
||||
break;
|
||||
default:
|
||||
changeToState(State.START);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void changeToState(State state) {
|
||||
switch (state) {
|
||||
case START: {
|
||||
mCurrentState = State.START;
|
||||
mStartFragment = StartFragment.newInstance();
|
||||
loadFragment(mStartFragment);
|
||||
mBackButton.setText(android.R.string.cancel);
|
||||
mNextButton.setText(R.string.btn_next);
|
||||
break;
|
||||
}
|
||||
case CREATE_KEY: {
|
||||
mCurrentState = State.CREATE_KEY;
|
||||
mCreateKeyFragment = CreateKeyFragment.newInstance();
|
||||
loadFragment(mCreateKeyFragment);
|
||||
break;
|
||||
}
|
||||
case IMPORT_KEY: {
|
||||
mCurrentState = State.IMPORT_KEY;
|
||||
Intent intent = new Intent(this, ImportKeysActivity.class);
|
||||
intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
|
||||
startActivityForResult(intent, REQUEST_CODE_IMPORT);
|
||||
break;
|
||||
}
|
||||
case K9: {
|
||||
mCurrentState = State.K9;
|
||||
mBackButton.setEnabled(false); // don't go back to import/create key
|
||||
mK9Fragment = K9Fragment.newInstance();
|
||||
loadFragment(mK9Fragment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,14 +32,15 @@ import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.helper.OtherHelper;
|
||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class SubkeysAdapter extends CursorAdapter {
|
||||
private LayoutInflater mInflater;
|
||||
private SaveKeyringParcel mSaveKeyringParcel;
|
||||
|
||||
private boolean hasAnySecret;
|
||||
|
||||
private ColorStateList mDefaultTextColor;
|
||||
|
||||
public static final String[] SUBKEYS_PROJECTION = new String[]{
|
||||
@@ -71,10 +72,21 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
private static final int INDEX_EXPIRY = 11;
|
||||
private static final int INDEX_FINGERPRINT = 12;
|
||||
|
||||
public SubkeysAdapter(Context context, Cursor c, int flags) {
|
||||
public SubkeysAdapter(Context context, Cursor c, int flags,
|
||||
SaveKeyringParcel saveKeyringParcel) {
|
||||
super(context, c, flags);
|
||||
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mSaveKeyringParcel = saveKeyringParcel;
|
||||
}
|
||||
|
||||
public SubkeysAdapter(Context context, Cursor c, int flags) {
|
||||
this(context, c, flags, null);
|
||||
}
|
||||
|
||||
public long getKeyId(int position) {
|
||||
mCursor.moveToPosition(position);
|
||||
return mCursor.getLong(INDEX_KEY_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,79 +106,94 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
TextView keyId = (TextView) view.findViewById(R.id.keyId);
|
||||
TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
|
||||
TextView keyExpiry = (TextView) view.findViewById(R.id.keyExpiry);
|
||||
ImageView masterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
|
||||
ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
|
||||
ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
|
||||
ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
|
||||
ImageView revokedKeyIcon = (ImageView) view.findViewById(R.id.ic_revokedKey);
|
||||
TextView vKeyId = (TextView) view.findViewById(R.id.keyId);
|
||||
TextView vKeyDetails = (TextView) view.findViewById(R.id.keyDetails);
|
||||
TextView vKeyExpiry = (TextView) view.findViewById(R.id.keyExpiry);
|
||||
ImageView vMasterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
|
||||
ImageView vCertifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
|
||||
ImageView vEncryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
|
||||
ImageView vSignIcon = (ImageView) view.findViewById(R.id.ic_signKey);
|
||||
ImageView vRevokedKeyIcon = (ImageView) view.findViewById(R.id.ic_revokedKey);
|
||||
ImageView vEditImage = (ImageView) view.findViewById(R.id.edit_image);
|
||||
|
||||
String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(INDEX_KEY_ID));
|
||||
long keyId = cursor.getLong(INDEX_KEY_ID);
|
||||
String keyIdStr = PgpKeyHelper.convertKeyIdToHex(keyId);
|
||||
String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
|
||||
context,
|
||||
cursor.getInt(INDEX_ALGORITHM),
|
||||
cursor.getInt(INDEX_KEY_SIZE)
|
||||
);
|
||||
|
||||
keyId.setText(keyIdStr);
|
||||
vKeyId.setText(keyIdStr);
|
||||
// may be set with additional "stripped" later on
|
||||
if (hasAnySecret && cursor.getInt(INDEX_HAS_SECRET) == 0) {
|
||||
keyDetails.setText(algorithmStr + ", " +
|
||||
vKeyDetails.setText(algorithmStr + ", " +
|
||||
context.getString(R.string.key_stripped));
|
||||
} else {
|
||||
keyDetails.setText(algorithmStr);
|
||||
vKeyDetails.setText(algorithmStr);
|
||||
}
|
||||
|
||||
// Set icons according to properties
|
||||
masterKeyIcon.setVisibility(cursor.getInt(INDEX_RANK) == 0 ? View.VISIBLE : View.INVISIBLE);
|
||||
certifyIcon.setVisibility(cursor.getInt(INDEX_CAN_CERTIFY) != 0 ? View.VISIBLE : View.GONE);
|
||||
encryptIcon.setVisibility(cursor.getInt(INDEX_CAN_ENCRYPT) != 0 ? View.VISIBLE : View.GONE);
|
||||
signIcon.setVisibility(cursor.getInt(INDEX_CAN_SIGN) != 0 ? View.VISIBLE : View.GONE);
|
||||
vMasterKeyIcon.setVisibility(cursor.getInt(INDEX_RANK) == 0 ? View.VISIBLE : View.INVISIBLE);
|
||||
vCertifyIcon.setVisibility(cursor.getInt(INDEX_CAN_CERTIFY) != 0 ? View.VISIBLE : View.GONE);
|
||||
vEncryptIcon.setVisibility(cursor.getInt(INDEX_CAN_ENCRYPT) != 0 ? View.VISIBLE : View.GONE);
|
||||
vSignIcon.setVisibility(cursor.getInt(INDEX_CAN_SIGN) != 0 ? View.VISIBLE : View.GONE);
|
||||
|
||||
boolean valid = true;
|
||||
if (cursor.getInt(INDEX_IS_REVOKED) > 0) {
|
||||
revokedKeyIcon.setVisibility(View.VISIBLE);
|
||||
boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
|
||||
|
||||
valid = false;
|
||||
// for edit key
|
||||
if (mSaveKeyringParcel != null) {
|
||||
boolean revokeThisSubkey = (mSaveKeyringParcel.mRevokeSubKeys.contains(keyId));
|
||||
|
||||
if (revokeThisSubkey) {
|
||||
if (!isRevoked) {
|
||||
isRevoked = true;
|
||||
}
|
||||
}
|
||||
|
||||
vEditImage.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
keyId.setTextColor(mDefaultTextColor);
|
||||
keyDetails.setTextColor(mDefaultTextColor);
|
||||
keyExpiry.setTextColor(mDefaultTextColor);
|
||||
|
||||
revokedKeyIcon.setVisibility(View.GONE);
|
||||
vEditImage.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (isRevoked) {
|
||||
vRevokedKeyIcon.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
vKeyId.setTextColor(mDefaultTextColor);
|
||||
vKeyDetails.setTextColor(mDefaultTextColor);
|
||||
vKeyExpiry.setTextColor(mDefaultTextColor);
|
||||
|
||||
vRevokedKeyIcon.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
boolean isExpired;
|
||||
if (!cursor.isNull(INDEX_EXPIRY)) {
|
||||
Date expiryDate = new Date(cursor.getLong(INDEX_EXPIRY) * 1000);
|
||||
isExpired = expiryDate.before(new Date());
|
||||
|
||||
valid = valid && expiryDate.after(new Date());
|
||||
keyExpiry.setText(
|
||||
context.getString(R.string.label_expiry) + ": " +
|
||||
DateFormat.getDateFormat(context).format(expiryDate)
|
||||
);
|
||||
vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": "
|
||||
+ DateFormat.getDateFormat(context).format(expiryDate));
|
||||
} else {
|
||||
keyExpiry.setText(
|
||||
context.getString(R.string.label_expiry) + ": " +
|
||||
context.getString(R.string.none)
|
||||
);
|
||||
isExpired = false;
|
||||
|
||||
vKeyExpiry.setText(context.getString(R.string.label_expiry) + ": " + context.getString(R.string.none));
|
||||
}
|
||||
|
||||
// if key is expired or revoked, strike through text
|
||||
if (!valid) {
|
||||
keyId.setText(OtherHelper.strikeOutText(keyId.getText()));
|
||||
keyDetails.setText(OtherHelper.strikeOutText(keyDetails.getText()));
|
||||
keyExpiry.setText(OtherHelper.strikeOutText(keyExpiry.getText()));
|
||||
boolean isInvalid = isRevoked || isExpired;
|
||||
if (isInvalid) {
|
||||
vKeyId.setText(OtherHelper.strikeOutText(vKeyId.getText()));
|
||||
vKeyDetails.setText(OtherHelper.strikeOutText(vKeyDetails.getText()));
|
||||
vKeyExpiry.setText(OtherHelper.strikeOutText(vKeyExpiry.getText()));
|
||||
}
|
||||
keyId.setEnabled(valid);
|
||||
keyDetails.setEnabled(valid);
|
||||
keyExpiry.setEnabled(valid);
|
||||
vKeyId.setEnabled(!isInvalid);
|
||||
vKeyDetails.setEnabled(!isInvalid);
|
||||
vKeyExpiry.setEnabled(!isInvalid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
View view = mInflater.inflate(R.layout.view_key_keys_item, null);
|
||||
View view = mInflater.inflate(R.layout.view_key_subkey_item, null);
|
||||
if (mDefaultTextColor == null) {
|
||||
TextView keyId = (TextView) view.findViewById(R.id.keyId);
|
||||
mDefaultTextColor = keyId.getTextColors();
|
||||
@@ -177,13 +204,21 @@ public class SubkeysAdapter extends CursorAdapter {
|
||||
// Disable selection of items, http://stackoverflow.com/a/4075045
|
||||
@Override
|
||||
public boolean areAllItemsEnabled() {
|
||||
return false;
|
||||
if (mSaveKeyringParcel == null) {
|
||||
return false;
|
||||
} else {
|
||||
return super.areAllItemsEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
// Disable selection of items, http://stackoverflow.com/a/4075045
|
||||
@Override
|
||||
public boolean isEnabled(int position) {
|
||||
return false;
|
||||
if (mSaveKeyringParcel == null) {
|
||||
return false;
|
||||
} else {
|
||||
return super.isEnabled(position);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -40,9 +40,7 @@ import java.util.ArrayList;
|
||||
|
||||
public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemClickListener {
|
||||
private LayoutInflater mInflater;
|
||||
|
||||
private final ArrayList<Boolean> mCheckStates;
|
||||
|
||||
private SaveKeyringParcel mSaveKeyringParcel;
|
||||
|
||||
public static final String[] USER_IDS_PROJECTION = new String[]{
|
||||
@@ -60,7 +58,6 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
|
||||
private static final int INDEX_IS_PRIMARY = 4;
|
||||
private static final int INDEX_IS_REVOKED = 5;
|
||||
|
||||
|
||||
public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes,
|
||||
SaveKeyringParcel saveKeyringParcel) {
|
||||
super(context, c, flags);
|
||||
@@ -134,15 +131,18 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
|
||||
|
||||
// for edit key
|
||||
if (mSaveKeyringParcel != null) {
|
||||
boolean changeAnyPrimaryUserId = (mSaveKeyringParcel.changePrimaryUserId != null);
|
||||
boolean changeThisPrimaryUserId = (mSaveKeyringParcel.changePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.changePrimaryUserId.equals(userId));
|
||||
boolean revokeThisUserId = (mSaveKeyringParcel.revokeUserIds.contains(userId));
|
||||
boolean changeAnyPrimaryUserId = (mSaveKeyringParcel.mChangePrimaryUserId != null);
|
||||
boolean changeThisPrimaryUserId = (mSaveKeyringParcel.mChangePrimaryUserId != null
|
||||
&& mSaveKeyringParcel.mChangePrimaryUserId.equals(userId));
|
||||
boolean revokeThisUserId = (mSaveKeyringParcel.mRevokeUserIds.contains(userId));
|
||||
|
||||
// only if primary user id will be changed
|
||||
// (this is not triggered if the user id is currently the primary one)
|
||||
if (changeAnyPrimaryUserId) {
|
||||
// change all user ids, only this one should be primary
|
||||
// change _all_ primary user ids and set new one to true
|
||||
isPrimary = changeThisPrimaryUserId;
|
||||
}
|
||||
|
||||
if (revokeThisUserId) {
|
||||
if (!isRevoked) {
|
||||
isRevoked = true;
|
||||
@@ -233,7 +233,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
|
||||
|
||||
@Override
|
||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||
View view = mInflater.inflate(R.layout.view_key_userids_item, null);
|
||||
View view = mInflater.inflate(R.layout.view_key_user_id_item, null);
|
||||
// only need to do this once ever, since mShowCheckBoxes is final
|
||||
view.findViewById(R.id.checkBox).setVisibility(mCheckStates != null ? View.VISIBLE : View.GONE);
|
||||
return view;
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.dialog;
|
||||
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.text.format.DateUtils;
|
||||
import android.widget.DatePicker;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class ChangeExpiryDialogFragment extends DialogFragment {
|
||||
private static final String ARG_MESSENGER = "messenger";
|
||||
private static final String ARG_CREATION_DATE = "creation_date";
|
||||
private static final String ARG_EXPIRY_DATE = "expiry_date";
|
||||
|
||||
public static final int MESSAGE_NEW_EXPIRY_DATE = 1;
|
||||
public static final String MESSAGE_DATA_EXPIRY_DATE = "expiry_date";
|
||||
|
||||
private Messenger mMessenger;
|
||||
private Calendar mCreationCal;
|
||||
private Calendar mExpiryCal;
|
||||
|
||||
private int mDatePickerResultCount = 0;
|
||||
private DatePickerDialog.OnDateSetListener mExpiryDateSetListener =
|
||||
new DatePickerDialog.OnDateSetListener() {
|
||||
public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
|
||||
// Note: Ignore results after the first one - android sends multiples.
|
||||
if (mDatePickerResultCount++ == 0) {
|
||||
Calendar selectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
selectedCal.set(year, monthOfYear, dayOfMonth);
|
||||
if (mExpiryCal != null) {
|
||||
long numDays = (selectedCal.getTimeInMillis() / 86400000)
|
||||
- (mExpiryCal.getTimeInMillis() / 86400000);
|
||||
if (numDays > 0) {
|
||||
Bundle data = new Bundle();
|
||||
data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime());
|
||||
sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data);
|
||||
}
|
||||
} else {
|
||||
Bundle data = new Bundle();
|
||||
data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, selectedCal.getTime());
|
||||
sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public class ExpiryDatePickerDialog extends DatePickerDialog {
|
||||
|
||||
public ExpiryDatePickerDialog(Context context, OnDateSetListener callBack,
|
||||
int year, int monthOfYear, int dayOfMonth) {
|
||||
super(context, callBack, year, monthOfYear, dayOfMonth);
|
||||
}
|
||||
|
||||
// set permanent title
|
||||
public void setTitle(CharSequence title) {
|
||||
super.setTitle(getContext().getString(R.string.expiry_date_dialog_title));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new instance of this dialog fragment
|
||||
*/
|
||||
public static ChangeExpiryDialogFragment newInstance(Messenger messenger,
|
||||
Date creationDate, Date expiryDate) {
|
||||
ChangeExpiryDialogFragment frag = new ChangeExpiryDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putParcelable(ARG_MESSENGER, messenger);
|
||||
args.putSerializable(ARG_CREATION_DATE, creationDate);
|
||||
args.putSerializable(ARG_EXPIRY_DATE, expiryDate);
|
||||
|
||||
frag.setArguments(args);
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates dialog
|
||||
*/
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
||||
Date creationDate = (Date) getArguments().getSerializable(ARG_CREATION_DATE);
|
||||
Date expiryDate = (Date) getArguments().getSerializable(ARG_EXPIRY_DATE);
|
||||
|
||||
mCreationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
mCreationCal.setTime(creationDate);
|
||||
mExpiryCal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||
mExpiryCal.setTime(expiryDate);
|
||||
|
||||
/*
|
||||
* Using custom DatePickerDialog which overrides the setTitle because
|
||||
* the DatePickerDialog title is buggy (unix warparound bug).
|
||||
* See: https://code.google.com/p/android/issues/detail?id=49066
|
||||
*/
|
||||
DatePickerDialog dialog = new ExpiryDatePickerDialog(getActivity(),
|
||||
mExpiryDateSetListener, mExpiryCal.get(Calendar.YEAR), mExpiryCal.get(Calendar.MONTH),
|
||||
mExpiryCal.get(Calendar.DAY_OF_MONTH));
|
||||
mDatePickerResultCount = 0;
|
||||
dialog.setCancelable(true);
|
||||
dialog.setButton(Dialog.BUTTON_NEGATIVE,
|
||||
getActivity().getString(R.string.btn_no_date),
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
// Note: Ignore results after the first one - android sends multiples.
|
||||
if (mDatePickerResultCount++ == 0) {
|
||||
// none expiry dates corresponds to a null message
|
||||
Bundle data = new Bundle();
|
||||
data.putSerializable(MESSAGE_DATA_EXPIRY_DATE, null);
|
||||
sendMessageToHandler(MESSAGE_NEW_EXPIRY_DATE, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// setCalendarViewShown() is supported from API 11 onwards.
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||
// Hide calendarView in tablets because of the unix warparound bug.
|
||||
dialog.getDatePicker().setCalendarViewShown(false);
|
||||
}
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) {
|
||||
// will crash with IllegalArgumentException if we set a min date
|
||||
// that is not before expiry
|
||||
if (mCreationCal != null && mCreationCal.before(mExpiryCal)) {
|
||||
dialog.getDatePicker().setMinDate(mCreationCal.getTime().getTime()
|
||||
+ DateUtils.DAY_IN_MILLIS);
|
||||
} else {
|
||||
// When created date isn't available
|
||||
dialog.getDatePicker().setMinDate(mExpiryCal.getTime().getTime()
|
||||
+ DateUtils.DAY_IN_MILLIS);
|
||||
}
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message back to handler which is initialized in a activity
|
||||
*
|
||||
* @param what Message integer you want to send
|
||||
*/
|
||||
private void sendMessageToHandler(Integer what, Bundle data) {
|
||||
Message msg = Message.obtain();
|
||||
msg.what = what;
|
||||
if (data != null) {
|
||||
msg.setData(data);
|
||||
}
|
||||
|
||||
try {
|
||||
mMessenger.send(msg);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
|
||||
} catch (NullPointerException e) {
|
||||
Log.w(Constants.TAG, "Messenger is null!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.os.RemoteException;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
|
||||
public class EditSubkeyDialogFragment extends DialogFragment {
|
||||
private static final String ARG_MESSENGER = "messenger";
|
||||
|
||||
public static final int MESSAGE_CHANGE_EXPIRY = 1;
|
||||
public static final int MESSAGE_REVOKE = 2;
|
||||
|
||||
private Messenger mMessenger;
|
||||
|
||||
/**
|
||||
* Creates new instance of this dialog fragment
|
||||
*/
|
||||
public static EditSubkeyDialogFragment newInstance(Messenger messenger) {
|
||||
EditSubkeyDialogFragment frag = new EditSubkeyDialogFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putParcelable(ARG_MESSENGER, messenger);
|
||||
|
||||
frag.setArguments(args);
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates dialog
|
||||
*/
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
|
||||
|
||||
CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(getActivity());
|
||||
CharSequence[] array = getResources().getStringArray(R.array.edit_key_edit_subkey);
|
||||
|
||||
builder.setTitle(R.string.edit_key_edit_subkey_title);
|
||||
builder.setItems(array, new DialogInterface.OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case 0:
|
||||
sendMessageToHandler(MESSAGE_CHANGE_EXPIRY, null);
|
||||
break;
|
||||
case 1:
|
||||
sendMessageToHandler(MESSAGE_REVOKE, null);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
return builder.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message back to handler which is initialized in a activity
|
||||
*
|
||||
* @param what Message integer you want to send
|
||||
*/
|
||||
private void sendMessageToHandler(Integer what, Bundle data) {
|
||||
Message msg = Message.obtain();
|
||||
msg.what = what;
|
||||
if (data != null) {
|
||||
msg.setData(data);
|
||||
}
|
||||
|
||||
try {
|
||||
mMessenger.send(msg);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(Constants.TAG, "Exception sending message, Is handler present?", e);
|
||||
} catch (NullPointerException e) {
|
||||
Log.w(Constants.TAG, "Messenger is null!", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,7 +152,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
// above can't be statically verified to have been set in all cases because
|
||||
// the catch clause doesn't return.
|
||||
try {
|
||||
userId = secretRing.getPrimaryUserId();
|
||||
userId = secretRing.getPrimaryUserIdWithFallback();
|
||||
} catch (PgpGeneralException e) {
|
||||
userId = null;
|
||||
}
|
||||
@@ -189,7 +189,8 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
|
||||
// Early breakout if we are dealing with a symmetric key
|
||||
if (secretRing == null) {
|
||||
PassphraseCacheService.addCachedPassphrase(activity, Constants.key.symmetric, passphrase);
|
||||
PassphraseCacheService.addCachedPassphrase(activity, Constants.key.symmetric,
|
||||
passphrase, getString(R.string.passp_cache_notif_pwd));
|
||||
// also return passphrase back to activity
|
||||
Bundle data = new Bundle();
|
||||
data.putString(MESSAGE_DATA_PASSPHRASE, passphrase);
|
||||
@@ -228,10 +229,18 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
|
||||
|
||||
// cache the new passphrase
|
||||
Log.d(Constants.TAG, "Everything okay! Caching entered passphrase");
|
||||
PassphraseCacheService.addCachedPassphrase(activity, masterKeyId, passphrase);
|
||||
|
||||
try {
|
||||
PassphraseCacheService.addCachedPassphrase(activity, masterKeyId, passphrase,
|
||||
secretRing.getPrimaryUserIdWithFallback());
|
||||
} catch(PgpGeneralException e) {
|
||||
Log.e(Constants.TAG, "adding of a passhrase failed", e);
|
||||
}
|
||||
|
||||
if (unlockedSecretKey.getKeyId() != masterKeyId) {
|
||||
PassphraseCacheService.addCachedPassphrase(
|
||||
activity, unlockedSecretKey.getKeyId(), passphrase);
|
||||
activity, unlockedSecretKey.getKeyId(), passphrase,
|
||||
unlockedSecretKey.getPrimaryUserIdWithFallback());
|
||||
}
|
||||
|
||||
// also return passphrase back to activity
|
||||
|
||||
Reference in New Issue
Block a user