Preparations for support of onion keyservers. Refactoring of Keyserver and proxy related classes

This commit is contained in:
Dominik Schürmann
2016-10-27 16:19:43 +02:00
parent bf382ec59d
commit 911fa020c2
37 changed files with 576 additions and 479 deletions

View File

@@ -53,6 +53,7 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
@@ -501,7 +502,7 @@ public class CreateKeyFinalFragment extends Fragment {
// set data uri as path to keyring
final long masterKeyId = saveKeyResult.mMasterKeyId;
// upload to favorite keyserver
final String keyserver = Preferences.getPreferences(activity).getPreferredKeyserver();
final ParcelableHkpKeyserver keyserver = Preferences.getPreferences(activity).getPreferredKeyserver();
CryptoOperationHelper.Callback<UploadKeyringParcel, UploadResult> callback
= new CryptoOperationHelper.Callback<UploadKeyringParcel, UploadResult>() {

View File

@@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.SecurityTokenListenerFragment;
import org.sufficientlysecure.keychain.ui.base.QueueingCryptoOperationFragment;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Preferences;
@@ -73,7 +74,7 @@ public class CreateSecurityTokenImportResetFragment
private View mResetWarning;
// for CryptoOperationFragment key import
private String mKeyserver;
private ParcelableHkpKeyserver mKeyserver;
private ArrayList<ParcelableKeyRing> mKeyList;
public static Fragment newInstance(byte[] scannedFingerprints, byte[] nfcAid, String userId) {

View File

@@ -56,6 +56,7 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Preferences;
public abstract class DecryptFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
@@ -137,7 +138,7 @@ public abstract class DecryptFragment extends Fragment implements LoaderManager.
private void lookupUnknownKey(long unknownKeyId) {
final ArrayList<ParcelableKeyRing> keyList;
final String keyserver;
final ParcelableHkpKeyserver keyserver;
// search config
keyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();

View File

@@ -94,6 +94,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify.Style;
import org.sufficientlysecure.keychain.util.FileHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableHashMap;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Preferences;
@@ -759,7 +760,7 @@ public class DecryptListFragment
private void lookupUnknownKey(final Uri inputUri, long unknownKeyId) {
final ArrayList<ParcelableKeyRing> keyList;
final String keyserver;
final ParcelableHkpKeyserver keyserver;
// search config
keyserver = Preferences.getPreferences(getActivity()).getPreferredKeyserver();

View File

@@ -38,6 +38,7 @@ import android.widget.TextView;
import org.openintents.openpgp.util.OpenPgpUtils;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.operations.results.DeleteResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.operations.results.RevokeResult;
@@ -154,7 +155,7 @@ public class DeleteKeyDialogActivity extends FragmentActivity {
@Override
public RevokeKeyringParcel createOperationInput() {
return new RevokeKeyringParcel(mMasterKeyIds[0], true,
getIntent().getStringExtra(EXTRA_KEYSERVER));
(ParcelableHkpKeyserver) getIntent().getParcelableExtra(EXTRA_KEYSERVER));
}
@Override

View File

@@ -62,6 +62,7 @@ import org.sufficientlysecure.keychain.ui.dialog.AddUserIdDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Preferences;
public class EditIdentitiesFragment extends Fragment
@@ -387,7 +388,7 @@ public class EditIdentitiesFragment extends Fragment
final long masterKeyId = editKeyResult.mMasterKeyId;
// upload to favorite keyserver
final String keyserver = Preferences.getPreferences(activity).getPreferredKeyserver();
final ParcelableHkpKeyserver keyserver = Preferences.getPreferences(activity).getPreferredKeyserver();
CryptoOperationHelper.Callback<UploadKeyringParcel, UploadResult> callback
= new CryptoOperationHelper.Callback<UploadKeyringParcel, UploadResult>() {

View File

@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
import org.sufficientlysecure.keychain.util.ParcelableFileCache.IteratorWithSize;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Preferences;
import java.io.IOException;
@@ -79,7 +80,7 @@ public class ImportKeysActivity extends BaseActivity
public static final String TAG_FRAG_TOP = "frag_top";
// for CryptoOperationHelper.Callback
private String mKeyserver;
private ParcelableHkpKeyserver mKeyserver;
private ArrayList<ParcelableKeyRing> mKeyList;
private CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult> mOperationHelper;
@@ -233,8 +234,9 @@ public class ImportKeysActivity extends BaseActivity
Notify.create(this, R.string.import_url_warn_no_search_parameter, Notify.LENGTH_INDEFINITE,
Notify.Style.WARN).show();
}
ParcelableHkpKeyserver keyserver = new ParcelableHkpKeyserver(dataUri.getAuthority());
Preferences.CloudSearchPrefs cloudSearchPrefs = new Preferences.CloudSearchPrefs(
true, true, true, dataUri.getAuthority());
true, true, true, keyserver);
// we allow our users to edit the query if they wish
startTopCloudFragment(query, false, cloudSearchPrefs);
// search immediately (if query is not null)

View File

@@ -43,6 +43,7 @@ import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
@@ -62,7 +63,7 @@ public class ImportKeysProxyActivity extends FragmentActivity
public static final String EXTRA_FINGERPRINT = "fingerprint";
// for CryptoOperationHelper
private String mKeyserver;
private ParcelableHkpKeyserver mKeyserver;
private ArrayList<ParcelableKeyRing> mKeyList;
private CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult> mImportOpHelper;

View File

@@ -76,6 +76,7 @@ import org.sufficientlysecure.keychain.ui.util.ContentDescriptionHint;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.FabContainer;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Preferences;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
@@ -111,7 +112,7 @@ public class KeyListFragment extends LoaderFragment
// for CryptoOperationHelper import
private ArrayList<ParcelableKeyRing> mKeyList;
private String mKeyserver;
private ParcelableHkpKeyserver mKeyserver;
private CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult> mImportOpHelper;
// for ConsolidateOperation

View File

@@ -41,6 +41,7 @@ import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableFileCache;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import java.io.IOException;
import java.util.ArrayList;
@@ -61,7 +62,7 @@ public class SafeSlingerActivity extends BaseActivity
// for CryptoOperationHelper
private ArrayList<ParcelableKeyRing> mKeyList;
private String mKeyserver;
private ParcelableHkpKeyserver mKeyserver;
private CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult> mOperationHelper;

View File

@@ -53,10 +53,12 @@ import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.util.ArrayList;
import java.util.List;
public class SettingsActivity extends AppCompatPreferenceActivity {
@@ -180,9 +182,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
public static String keyserverSummary(Context context) {
String[] servers = sPreferences.getKeyServers();
ArrayList<ParcelableHkpKeyserver> servers = sPreferences.getKeyServers();
String serverSummary = context.getResources().getQuantityString(
R.plurals.n_keyservers, servers.length, servers.length);
R.plurals.n_keyservers, servers.size(), servers.size());
return serverSummary + "; " + context.getString(R.string.label_preferred) + ": " + sPreferences
.getPreferredKeyserver();
}

View File

@@ -22,8 +22,11 @@ import android.os.Bundle;
import android.view.MenuItem;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import java.util.ArrayList;
public class SettingsKeyServerActivity extends BaseActivity {
public static final String EXTRA_KEY_SERVERS = "key_servers";
@@ -33,7 +36,7 @@ public class SettingsKeyServerActivity extends BaseActivity {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String servers[] = intent.getStringArrayExtra(EXTRA_KEY_SERVERS);
ArrayList<ParcelableHkpKeyserver> servers = intent.getParcelableArrayListExtra(EXTRA_KEY_SERVERS);
loadFragment(savedInstanceState, servers);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@@ -55,7 +58,7 @@ public class SettingsKeyServerActivity extends BaseActivity {
setContentView(R.layout.key_server_preference);
}
private void loadFragment(Bundle savedInstanceState, String[] keyservers) {
private void loadFragment(Bundle savedInstanceState, ArrayList<ParcelableHkpKeyserver> keyservers) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.

View File

@@ -18,7 +18,6 @@
package org.sufficientlysecure.keychain.ui;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -41,29 +40,28 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.dialog.AddEditKeyserverDialogFragment;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperAdapter;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperViewHolder;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperDragCallback;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperAdapter;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperDragCallback;
import org.sufficientlysecure.keychain.ui.util.recyclerview.ItemTouchHelperViewHolder;
import org.sufficientlysecure.keychain.ui.util.recyclerview.RecyclerItemClickListener;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SettingsKeyserverFragment extends Fragment implements RecyclerItemClickListener.OnItemClickListener {
private static final String ARG_KEYSERVER_ARRAY = "arg_keyserver_array";
private ItemTouchHelper mItemTouchHelper;
private ArrayList<String> mKeyservers;
private ArrayList<ParcelableHkpKeyserver> mKeyservers;
private KeyserverListAdapter mAdapter;
public static SettingsKeyserverFragment newInstance(String[] keyservers) {
public static SettingsKeyserverFragment newInstance(ArrayList<ParcelableHkpKeyserver> keyservers) {
Bundle args = new Bundle();
args.putStringArray(ARG_KEYSERVER_ARRAY, keyservers);
args.putParcelableArrayList(ARG_KEYSERVER_ARRAY, keyservers);
SettingsKeyserverFragment fragment = new SettingsKeyserverFragment();
fragment.setArguments(args);
@@ -82,8 +80,7 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
String keyservers[] = getArguments().getStringArray(ARG_KEYSERVER_ARRAY);
mKeyservers = new ArrayList<>(Arrays.asList(keyservers));
mKeyservers = getArguments().getParcelableArrayList(ARG_KEYSERVER_ARRAY);
mAdapter = new KeyserverListAdapter(mKeyservers);
@@ -133,7 +130,7 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
}
private void startEditKeyserverDialog(AddEditKeyserverDialogFragment.DialogAction action,
String keyserver, final int position) {
ParcelableHkpKeyserver keyserver, final int position) {
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
@@ -162,7 +159,7 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
R.string.add_keyserver_without_verification,
Notify.Style.WARN).show();
}
String keyserver = data.getString(
ParcelableHkpKeyserver keyserver = data.getParcelable(
AddEditKeyserverDialogFragment.MESSAGE_KEYSERVER);
AddEditKeyserverDialogFragment.DialogAction dialogAction
@@ -189,13 +186,13 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
dialogFragment.show(getFragmentManager(), "addKeyserverDialog");
}
private void addKeyserver(String keyserver) {
private void addKeyserver(ParcelableHkpKeyserver keyserver) {
mKeyservers.add(keyserver);
mAdapter.notifyItemInserted(mKeyservers.size() - 1);
saveKeyserverList();
}
private void editKeyserver(String newKeyserver, int position) {
private void editKeyserver(ParcelableHkpKeyserver newKeyserver, int position) {
mKeyservers.set(position, newKeyserver);
mAdapter.notifyItemChanged(position);
saveKeyserverList();
@@ -218,8 +215,7 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
}
private void saveKeyserverList() {
String servers[] = mKeyservers.toArray(new String[mKeyservers.size()]);
Preferences.getPreferences(getActivity()).setKeyServers(servers);
Preferences.getPreferences(getActivity()).setKeyServers(mKeyservers);
}
@Override
@@ -231,9 +227,9 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
public class KeyserverListAdapter extends RecyclerView.Adapter<KeyserverListAdapter.ViewHolder>
implements ItemTouchHelperAdapter {
private final List<String> mKeyservers;
private final ArrayList<ParcelableHkpKeyserver> mKeyservers;
public KeyserverListAdapter(List<String> keyservers) {
public KeyserverListAdapter(ArrayList<ParcelableHkpKeyserver> keyservers) {
mKeyservers = keyservers;
}
@@ -246,7 +242,7 @@ public class SettingsKeyserverFragment extends Fragment implements RecyclerItemC
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.keyserverUrl.setText(mKeyservers.get(position));
holder.keyserverUrl.setText(mKeyservers.get(position).getUrl());
// Start a drag whenever the handle view it touched
holder.dragHandleView.setOnTouchListener(new View.OnTouchListener() {

View File

@@ -35,9 +35,12 @@ import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Preferences;
import java.util.ArrayList;
/**
* Sends the selected public key to a keyserver
*/
@@ -49,7 +52,7 @@ public class UploadKeyActivity extends BaseActivity
private Uri mDataUri;
// CryptoOperationHelper.Callback vars
private String mKeyserver;
private ParcelableHkpKeyserver mKeyserver;
private CryptoOperationHelper<UploadKeyringParcel, UploadResult> mUploadOpHelper;
@Override
@@ -64,8 +67,7 @@ public class UploadKeyActivity extends BaseActivity
mMultiUserIdsFragment.setCheckboxVisibility(false);
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_item, Preferences.getPreferences(this)
.getKeyServers()
android.R.layout.simple_spinner_item, getKeyserversArray()
);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mKeyServerSpinner.setAdapter(adapter);
@@ -91,6 +93,18 @@ public class UploadKeyActivity extends BaseActivity
}
private String[] getKeyserversArray() {
ArrayList<ParcelableHkpKeyserver> keyservers = Preferences.getPreferences(this)
.getKeyServers();
String[] keyserversArray = new String[keyservers.size()];
int i = 0;
for (ParcelableHkpKeyserver k : keyservers) {
keyserversArray[i] = k.getUrl();
i++;
}
return keyserversArray;
}
@Override
protected void initLayout() {
setContentView(R.layout.upload_key_activity);
@@ -105,8 +119,7 @@ public class UploadKeyActivity extends BaseActivity
}
private void uploadKey() {
String server = (String) mKeyServerSpinner.getSelectedItem();
mKeyserver = server;
mKeyserver = (ParcelableHkpKeyserver) mKeyServerSpinner.getSelectedItem();
mUploadOpHelper = new CryptoOperationHelper<>(1, this, this, R.string.progress_uploading);
mUploadOpHelper.cryptoOperation();

View File

@@ -100,6 +100,7 @@ import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
import org.sufficientlysecure.keychain.util.ContactHelper;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.NfcHelper;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Passphrase;
import org.sufficientlysecure.keychain.util.Preferences;
@@ -128,7 +129,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements
protected Uri mDataUri;
// For CryptoOperationHelper.Callback
private String mKeyserver;
private ParcelableHkpKeyserver mKeyserver;
private ArrayList<ParcelableKeyRing> mKeyList;
private CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult> mImportOpHelper;
private CryptoOperationHelper<ChangeUnlockParcel, EditKeyResult> mEditOpHelper;

View File

@@ -182,13 +182,13 @@ public class ViewKeyKeybaseFragment extends LoaderFragment implements
}
private void startSearch(final String fingerprint) {
final Preferences.ProxyPrefs proxyPrefs =
Preferences.getPreferences(getActivity()).getProxyPrefs();
final ParcelableProxy parcelableProxy =
Preferences.getPreferences(getActivity()).getParcelableProxy();
OrbotHelper.DialogActions dialogActions = new OrbotHelper.DialogActions() {
@Override
public void onOrbotStarted() {
new DescribeKey(proxyPrefs.parcelableProxy).execute(fingerprint);
new DescribeKey(parcelableProxy).execute(fingerprint);
}
@Override
@@ -204,7 +204,7 @@ public class ViewKeyKeybaseFragment extends LoaderFragment implements
};
if (OrbotHelper.putOrbotInRequiredState(dialogActions, getActivity())) {
new DescribeKey(proxyPrefs.parcelableProxy).execute(fingerprint);
new DescribeKey(parcelableProxy).execute(fingerprint);
}
}

View File

@@ -112,13 +112,12 @@ public class ImportKeysListCloudLoader
* Query keyserver
*/
private void queryServer(boolean enforceFingerprint) {
ParcelableProxy parcelableProxy;
ParcelableProxy proxy;
if (mParcelableProxy == null) {
// no explicit proxy specified, fetch from preferences
if (OrbotHelper.isOrbotInRequiredState(mContext)) {
parcelableProxy = Preferences.getPreferences(mContext).getProxyPrefs()
.parcelableProxy;
proxy = Preferences.getPreferences(mContext).getParcelableProxy();
} else {
// user needs to enable/install orbot
mEntryList.clear();
@@ -129,14 +128,14 @@ public class ImportKeysListCloudLoader
return;
}
} else {
parcelableProxy = mParcelableProxy;
proxy = mParcelableProxy;
}
try {
ArrayList<ImportKeysListEntry> searchResult = CloudSearch.search(
mServerQuery,
mCloudPrefs,
parcelableProxy.getProxy()
proxy
);
mEntryList.clear();

View File

@@ -18,26 +18,20 @@
package org.sufficientlysecure.keychain.ui.dialog;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import android.app.Activity;
import android.support.design.widget.TextInputLayout;
import android.support.v7.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.annotation.NonNull;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -50,18 +44,23 @@ import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ParcelableHkpKeyserver;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.OkHttpClientFactory;
import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.TlsHelper;
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.net.Proxy;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
public class AddEditKeyserverDialogFragment extends DialogFragment implements OnEditorActionListener {
private static final String ARG_MESSENGER = "arg_messenger";
@@ -91,21 +90,22 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
EDIT
}
public enum FailureReason {
public enum VerifyReturn {
INVALID_URL,
CONNECTION_FAILED,
NO_PINNED_CERTIFICATE
NO_PINNED_CERTIFICATE,
GOOD
}
public static AddEditKeyserverDialogFragment newInstance(Messenger messenger,
DialogAction action,
String keyserver,
ParcelableHkpKeyserver keyserver,
int position) {
AddEditKeyserverDialogFragment frag = new AddEditKeyserverDialogFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_MESSENGER, messenger);
args.putSerializable(ARG_ACTION, action);
args.putString(ARG_KEYSERVER, keyserver);
args.putParcelable(ARG_KEYSERVER, keyserver);
args.putInt(ARG_POSITION, position);
frag.setArguments(args);
@@ -146,7 +146,8 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
}
case EDIT: {
alert.setTitle(R.string.edit_keyserver_dialog_title);
mKeyserverEditText.setText(getArguments().getString(ARG_KEYSERVER));
ParcelableHkpKeyserver keyserver = getArguments().getParcelable(ARG_KEYSERVER);
mKeyserverEditText.setText(keyserver.getUrl());
break;
}
}
@@ -226,16 +227,19 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
mKeyserverEditTextLayout.setErrorEnabled(false);
// behaviour same for edit and add
final String keyserverUrl = mKeyserverEditText.getText().toString();
String keyserverUrl = mKeyserverEditText.getText().toString();
// TODO!
String keyserverOnion = mKeyserverEditText.getText().toString();
final ParcelableHkpKeyserver keyserver = new ParcelableHkpKeyserver(keyserverUrl, keyserverOnion);
if (mVerifyKeyserverCheckBox.isChecked()) {
final Preferences.ProxyPrefs proxyPrefs = Preferences.getPreferences(getActivity())
.getProxyPrefs();
final ParcelableProxy proxy = Preferences.getPreferences(getActivity())
.getParcelableProxy();
OrbotHelper.DialogActions dialogActions = new OrbotHelper.DialogActions() {
@Override
public void onOrbotStarted() {
verifyConnection(
keyserverUrl,
proxyPrefs.parcelableProxy.getProxy(),
keyserver,
proxy,
mOnlyTrustedKeyserverCheckBox.isChecked()
);
}
@@ -243,7 +247,7 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
@Override
public void onNeutralButton() {
verifyConnection(
keyserverUrl,
keyserver,
null,
mOnlyTrustedKeyserverCheckBox.isChecked()
);
@@ -257,26 +261,26 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
if (OrbotHelper.putOrbotInRequiredState(dialogActions, getActivity())) {
verifyConnection(
keyserverUrl,
proxyPrefs.parcelableProxy.getProxy(),
keyserver,
proxy,
mOnlyTrustedKeyserverCheckBox.isChecked()
);
}
} else {
dismiss();
// return unverified keyserver back to activity
keyserverEdited(keyserverUrl, false);
keyserverEdited(new ParcelableHkpKeyserver(keyserverUrl, null), false);
}
}
});
}
}
public void keyserverEdited(String keyserver, boolean verified) {
public void keyserverEdited(ParcelableHkpKeyserver keyserver, boolean verified) {
dismiss();
Bundle data = new Bundle();
data.putSerializable(MESSAGE_DIALOG_ACTION, mDialogAction);
data.putString(MESSAGE_KEYSERVER, keyserver);
data.putParcelable(MESSAGE_KEYSERVER, keyserver);
data.putBoolean(MESSAGE_VERIFIED, verified);
if (mDialogAction == DialogAction.EDIT) {
@@ -296,8 +300,8 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
sendMessageToHandler(MESSAGE_OKAY, data);
}
public void verificationFailed(FailureReason failureReason) {
switch (failureReason) {
public void verificationFailed(VerifyReturn verifyReturn) {
switch (verifyReturn) {
case CONNECTION_FAILED: {
mKeyserverEditTextLayout.setError(
getString(R.string.add_keyserver_connection_failed));
@@ -317,11 +321,11 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
}
public void verifyConnection(String keyserver, final Proxy proxy, final boolean onlyTrustedKeyserver) {
public void verifyConnection(ParcelableHkpKeyserver keyserver, final ParcelableProxy proxy, final boolean onlyTrustedKeyserver) {
new AsyncTask<String, Void, FailureReason>() {
new AsyncTask<ParcelableHkpKeyserver, Void, VerifyReturn>() {
ProgressDialog mProgressDialog;
String mKeyserver;
ParcelableHkpKeyserver mKeyserver;
@Override
protected void onPreExecute() {
@@ -332,61 +336,62 @@ public class AddEditKeyserverDialogFragment extends DialogFragment implements On
}
@Override
protected FailureReason doInBackground(String... keyservers) {
protected VerifyReturn doInBackground(ParcelableHkpKeyserver... keyservers) {
mKeyserver = keyservers[0];
FailureReason reason = null;
try {
// replace hkps/hkp scheme and reconstruct Uri
Uri keyserverUri = Uri.parse(mKeyserver);
String scheme = keyserverUri.getScheme();
String schemeSpecificPart = keyserverUri.getSchemeSpecificPart();
String fragment = keyserverUri.getFragment();
if (scheme == null) {
throw new MalformedURLException();
}
if ("hkps".equalsIgnoreCase(scheme)) {
scheme = "https";
} else if ("hkp".equalsIgnoreCase(scheme)) {
scheme = "http";
}
URI newKeyserver = new URI(scheme, schemeSpecificPart, fragment);
Log.d("Converted URL", newKeyserver.toString());
if (onlyTrustedKeyserver
&& TlsHelper.getPinnedSslSocketFactory(newKeyserver.toURL()) == null) {
Log.w(Constants.TAG, "No pinned certificate for this host in OpenKeychain's assets.");
reason = FailureReason.NO_PINNED_CERTIFICATE;
return reason;
}
OkHttpClient client = OkHttpClientFactory.getClientPinnedIfAvailable(newKeyserver.toURL(), proxy);
client.newCall(new Request.Builder().url(newKeyserver.toURL()).build()).execute();
} catch (TlsHelper.TlsHelperException e) {
reason = FailureReason.CONNECTION_FAILED;
} catch (MalformedURLException | URISyntaxException e) {
Log.w(Constants.TAG, "Invalid keyserver URL entered by user.");
reason = FailureReason.INVALID_URL;
} catch (IOException e) {
Log.w(Constants.TAG, "Could not connect to entered keyserver url");
reason = FailureReason.CONNECTION_FAILED;
}
return reason;
return verifyKeyserver(mKeyserver, proxy, onlyTrustedKeyserver);
}
@Override
protected void onPostExecute(FailureReason failureReason) {
protected void onPostExecute(VerifyReturn verifyReturn) {
mProgressDialog.dismiss();
if (failureReason == null) {
if (verifyReturn == VerifyReturn.GOOD) {
keyserverEdited(mKeyserver, true);
} else {
verificationFailed(failureReason);
verificationFailed(verifyReturn);
}
}
}.execute(keyserver);
}
private VerifyReturn verifyKeyserver(ParcelableHkpKeyserver keyserver, final ParcelableProxy proxy, final boolean onlyTrustedKeyserver) {
VerifyReturn reason = VerifyReturn.GOOD;
try {
URI keyserverUriHttp = keyserver.getUrlURI();
// check TLS pinning only for non-Tor keyservers
if (onlyTrustedKeyserver
&& TlsHelper.getPinnedSslSocketFactory(keyserverUriHttp.toURL()) == null) {
Log.w(Constants.TAG, "No pinned certificate for this host in OpenKeychain's assets.");
reason = VerifyReturn.NO_PINNED_CERTIFICATE;
return reason;
}
OkHttpClient client = OkHttpClientFactory.getClientPinnedIfAvailable(
keyserverUriHttp.toURL(), proxy.getProxy());
client.newCall(new Request.Builder().url(keyserverUriHttp.toURL()).build()).execute();
// try out onion keyserver if Tor is enabled
if (proxy.isTorEnabled()) {
URI keyserverUriOnion = keyserver.getOnionURI();
OkHttpClient clientTor = OkHttpClientFactory.getClientPinnedIfAvailable(
keyserverUriOnion.toURL(), proxy.getProxy());
clientTor.newCall(new Request.Builder().url(keyserverUriOnion.toURL()).build()).execute();
}
} catch (TlsHelper.TlsHelperException e) {
reason = VerifyReturn.CONNECTION_FAILED;
} catch (MalformedURLException | URISyntaxException e) {
Log.w(Constants.TAG, "Invalid keyserver URL entered by user.");
reason = VerifyReturn.INVALID_URL;
} catch (IOException e) {
Log.w(Constants.TAG, "Could not connect to entered keyserver url");
reason = VerifyReturn.CONNECTION_FAILED;
}
return reason;
}
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);