added i2p support in CertifyKeyFragment and ImportKeyFragment

This commit is contained in:
Adithya Abraham Philip 2015-06-13 01:50:41 +05:30
parent b4f9eafa7b
commit d3fbd4f062
10 changed files with 173 additions and 44 deletions

View File

@ -50,6 +50,7 @@ dependencies {
compile 'com.mikepenz.iconics:community-material-typeface:1.0.0@aar' compile 'com.mikepenz.iconics:community-material-typeface:1.0.0@aar'
compile 'com.nispok:snackbar:2.10.8' compile 'com.nispok:snackbar:2.10.8'
compile 'com.squareup.okhttp:okhttp:2.4.0' compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'net.i2p.android:client:0.7@aar'
// libs as submodules // libs as submodules
compile project(':extern:openpgp-api-lib:openpgp-api') compile project(':extern:openpgp-api-lib:openpgp-api')
@ -188,6 +189,7 @@ android {
// Disable preDexing, causes com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000) on some systems // Disable preDexing, causes com.android.dx.cf.iface.ParseException: bad class file magic (cafebabe) or version (0034.0000) on some systems
dexOptions { dexOptions {
preDexLibraries = false preDexLibraries = false
javaMaxHeapSize = "4g"
} }
packagingOptions { packagingOptions {

View File

@ -66,8 +66,10 @@
<uses-permission android:name="android.permission.WRITE_PROFILE" /> <uses-permission android:name="android.permission.WRITE_PROFILE" />
<!-- android:allowBackup="false": Don't allow backup over adb backup or other apps! --> <!-- android:allowBackup="false": Don't allow backup over adb backup or other apps! -->
<!-- tools:replace="android:allowBackup" to accommodate "true" value in net.i2p.android -->
<application <application
android:name=".KeychainApplication" android:name=".KeychainApplication"
tools:replace="android:allowBackup"
android:allowBackup="false" android:allowBackup="false"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
android:icon="@drawable/ic_launcher" android:icon="@drawable/ic_launcher"

View File

@ -96,6 +96,7 @@ public final class Constants {
// proxy settings // proxy settings
public static final String USE_NORMAL_PROXY = "useNormalProxy"; public static final String USE_NORMAL_PROXY = "useNormalProxy";
public static final String USE_TOR_PROXY = "useTorProxy"; public static final String USE_TOR_PROXY = "useTorProxy";
public static final String USE_I2P_PROXY = "useI2pProxy";
public static final String PROXY_HOST = "proxyHost"; public static final String PROXY_HOST = "proxyHost";
public static final String PROXY_PORT = "proxyPort"; public static final String PROXY_PORT = "proxyPort";
public static final String PROXY_TYPE = "proxyType"; public static final String PROXY_TYPE = "proxyType";
@ -110,6 +111,15 @@ public final class Constants {
public static final Proxy.Type PROXY_TYPE = Proxy.Type.HTTP; public static final Proxy.Type PROXY_TYPE = Proxy.Type.HTTP;
} }
/**
* information to connect to I2P
*/
public static final class I2p {
public static final String PROXY_HOST = "127.0.0.1";
public static final int PROXY_PORT = 4444;
public static final Proxy.Type PROXY_TYPE = Proxy.Type.HTTP;
}
public static final class Defaults { public static final class Defaults {
public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, hkps://pgp.mit.edu"; public static final String KEY_SERVERS = "hkps://hkps.pool.sks-keyservers.net, hkps://pgp.mit.edu";
public static final int PREF_VERSION = 4; public static final int PREF_VERSION = 4;

View File

@ -41,6 +41,7 @@ import android.widget.CheckBox;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import net.i2p.android.ui.I2PAndroidHelper;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.operations.results.CertifyResult; import org.sufficientlysecure.keychain.operations.results.CertifyResult;
@ -175,22 +176,27 @@ public class CertifyKeyFragment
if (selectedKeyId == Constants.key.none) { if (selectedKeyId == Constants.key.none) {
Notify.create(getActivity(), getString(R.string.select_key_to_certify), Notify.create(getActivity(), getString(R.string.select_key_to_certify),
Notify.Style.ERROR).show(); Notify.Style.ERROR).show();
} else { } else { // check if proxy settings are valid before allowing operation
Runnable ignoreTor = new Runnable() {
if (mUploadKeyCheckbox.isChecked() && mProxyPrefs.torEnabled) {
Handler ignoreTorHandler = new Handler() {
@Override @Override
public void handleMessage(Message msg) { public void run() {
mProxyPrefs = new Preferences.ProxyPrefs(false, false, null, -1, null); mProxyPrefs = new Preferences.ProxyPrefs(Preferences.ProxyPrefs.Category.NONE, null, -1,
null);
cryptoOperation(); cryptoOperation();
} }
}; };
if (!OrbotHelper.isOrbotInstalled(getActivity())) {
OrbotHelper.getInstallDialogFragmentWithThirdButton(new Messenger(ignoreTorHandler), if (mUploadKeyCheckbox.isChecked() && mProxyPrefs.category == Preferences.ProxyPrefs.Category.TOR) {
R.string.orbot_install_dialog_ignore_tor).show(getActivity().getSupportFragmentManager(), "installOrbot"); OrbotHelper.isOrbotInRequiredState(R.string.orbot_ignore_tor, ignoreTor, mProxyPrefs,
} else if (!OrbotHelper.isOrbotRunning()) { getActivity());
OrbotHelper.getOrbotStartDialogFragment(new Messenger(ignoreTorHandler), }
R.string.orbot_install_dialog_ignore_tor).show(getActivity().getSupportFragmentManager(), "startOrbot");
if (mUploadKeyCheckbox.isChecked() && mProxyPrefs.category == Preferences.ProxyPrefs.Category.I2P) {
I2PAndroidHelper helper = new I2PAndroidHelper(getActivity());
if (!helper.isI2PAndroidInstalled()) {
helper.promptToInstall(getActivity());
} else if (!helper.isI2PAndroidRunning()) {
helper.requestI2PAndroidStart(getActivity());
} else { } else {
cryptoOperation(); cryptoOperation();
} }

View File

@ -355,7 +355,7 @@ public class ImportKeysActivity extends BaseNfcActivity {
@Override @Override
public void run() { public void run() {
// disables Tor until Activity is recreated // disables Tor until Activity is recreated
mProxyPrefs = new Preferences.ProxyPrefs(false, false, null, -1, null); mProxyPrefs = new Preferences.ProxyPrefs(Preferences.ProxyPrefs.Category.NONE, null, -1, null);
mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy); mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy);
} }
}; };

View File

@ -36,6 +36,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import net.i2p.android.ui.I2PAndroidHelper;
import org.spongycastle.bcpg.CompressionAlgorithmTags; import org.spongycastle.bcpg.CompressionAlgorithmTags;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
@ -303,6 +304,7 @@ public class SettingsActivity extends PreferenceActivity {
public static class Initializer { public static class Initializer {
private CheckBoxPreference mUseTor; private CheckBoxPreference mUseTor;
private CheckBoxPreference mUseI2p;
private CheckBoxPreference mUseNormalProxy; private CheckBoxPreference mUseNormalProxy;
private EditTextPreference mProxyHost; private EditTextPreference mProxyHost;
private EditTextPreference mProxyPort; private EditTextPreference mProxyPort;
@ -310,6 +312,10 @@ public class SettingsActivity extends PreferenceActivity {
private PreferenceActivity mActivity; private PreferenceActivity mActivity;
private PreferenceFragment mFragment; private PreferenceFragment mFragment;
private enum ProxyCategory {
TOR, I2P, NORMAL
}
public Initializer(PreferenceFragment fragment) { public Initializer(PreferenceFragment fragment) {
mFragment = fragment; mFragment = fragment;
} }
@ -341,17 +347,23 @@ public class SettingsActivity extends PreferenceActivity {
} }
mUseTor = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_TOR_PROXY); mUseTor = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_TOR_PROXY);
mUseI2p = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_I2P_PROXY);
mUseNormalProxy = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_NORMAL_PROXY); mUseNormalProxy = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_NORMAL_PROXY);
mProxyHost = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_HOST); mProxyHost = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_HOST);
mProxyPort = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_PORT); mProxyPort = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_PORT);
mProxyType = (ListPreference) automaticallyFindPreference(Constants.Pref.PROXY_TYPE); mProxyType = (ListPreference) automaticallyFindPreference(Constants.Pref.PROXY_TYPE);
initializeUseTorPref(); initializeUseTorPref();
initializeUseI2pPref();
initializeUseNormalProxyPref(); initializeUseNormalProxyPref();
initializeEditTextPreferences(); initializeEditTextPreferences();
initializeProxyTypePreference(); initializeProxyTypePreference();
if (mUseTor.isChecked()) disableNormalProxyPrefs(); if (mUseTor.isChecked()) disablePrefsOtherThan(ProxyCategory.TOR);
else if (mUseNormalProxy.isChecked()) disableUseTorPrefs(); else if (mUseNormalProxy.isChecked()) disablePrefsOtherThan(ProxyCategory.NORMAL);
else if (mUseI2p.isChecked()) disablePrefsOtherThan(ProxyCategory.I2P);
} }
private void initializeUseTorPref() { private void initializeUseTorPref() {
@ -368,14 +380,45 @@ public class SettingsActivity extends PreferenceActivity {
// don't let the user check the box until he's installed orbot // don't let the user check the box until he's installed orbot
return false; return false;
} else { } else {
disableNormalProxyPrefs(); disablePrefsOtherThan(ProxyCategory.TOR);
// let the enable tor box be checked // let the enable tor box be checked
return true; return true;
} }
} }
else { else {
// we're unchecking Tor, so enable other proxy // we're unchecking Tor, so enable other proxy
enableNormalProxyPrefs(); enableAllProxyPrefs();
return true;
}
}
});
}
private void initializeUseI2pPref() {
mUseI2p.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// checks whether the Initializer is being used from a fragment or activity, and acts
// accordingly
Activity activity = mFragment != null ? mFragment.getActivity() : mActivity;
if ((Boolean)newValue) {
I2PAndroidHelper i2pHelper = new I2PAndroidHelper(activity);
boolean installed = i2pHelper.isI2PAndroidInstalled();
if (!installed) {
Log.d(Constants.TAG, "Prompting to install I2P");
i2pHelper.promptToInstall(activity);
// don't let the user check the box until he's installed I2P
return false;
} else {
disablePrefsOtherThan(ProxyCategory.I2P);
// let the enable I2P box be checked
return true;
}
}
else {
// we're unchecking I2P, so enable other proxy options
enableAllProxyPrefs();
return true; return true;
} }
} }
@ -387,9 +430,9 @@ public class SettingsActivity extends PreferenceActivity {
@Override @Override
public boolean onPreferenceChange(Preference preference, Object newValue) { public boolean onPreferenceChange(Preference preference, Object newValue) {
if ((Boolean) newValue) { if ((Boolean) newValue) {
disableUseTorPrefs(); disablePrefsOtherThan(ProxyCategory.NORMAL);
} else { } else {
enableUseTorPrefs(); enableAllProxyPrefs();
} }
return true; return true;
} }
@ -460,6 +503,29 @@ public class SettingsActivity extends PreferenceActivity {
}); });
} }
private void disablePrefsOtherThan(ProxyCategory type) {
switch(type) {
case TOR:
disableNormalProxyPrefs();
disableI2pPrefs();
break;
case I2P:
disableTorPrefs();
disableNormalProxyPrefs();
break;
case NORMAL:
disableI2pPrefs();
disableTorPrefs();
break;
}
}
private void enableAllProxyPrefs() {
enableTorPrefs();
enableI2pPrefs();
enableNormalProxyPrefs();
}
private void disableNormalProxyPrefs() { private void disableNormalProxyPrefs() {
mUseNormalProxy.setChecked(false); mUseNormalProxy.setChecked(false);
mUseNormalProxy.setEnabled(false); mUseNormalProxy.setEnabled(false);
@ -475,14 +541,23 @@ public class SettingsActivity extends PreferenceActivity {
mProxyType.setEnabled(true); mProxyType.setEnabled(true);
} }
private void disableUseTorPrefs() { private void disableTorPrefs() {
mUseTor.setChecked(false); mUseTor.setChecked(false);
mUseTor.setEnabled(false); mUseTor.setEnabled(false);
} }
private void enableUseTorPrefs() { private void enableTorPrefs() {
mUseTor.setEnabled(true); mUseTor.setEnabled(true);
} }
private void disableI2pPrefs() {
mUseI2p.setChecked(false);
mUseI2p.setEnabled(false);
}
private void enableI2pPrefs() {
mUseI2p.setEnabled(true);
}
} }
} }
@ -491,6 +566,7 @@ public class SettingsActivity extends PreferenceActivity {
protected boolean isValidFragment(String fragmentName) { protected boolean isValidFragment(String fragmentName) {
return AdvancedPrefsFragment.class.getName().equals(fragmentName) return AdvancedPrefsFragment.class.getName().equals(fragmentName)
|| CloudSearchPrefsFragment.class.getName().equals(fragmentName) || CloudSearchPrefsFragment.class.getName().equals(fragmentName)
|| ProxyPrefsFragment.class.getName().equals(fragmentName)
|| super.isValidFragment(fragmentName); || super.isValidFragment(fragmentName);
} }

View File

@ -247,6 +247,10 @@ public class Preferences {
return mSharedPreferences.getBoolean(Constants.Pref.USE_TOR_PROXY, false); return mSharedPreferences.getBoolean(Constants.Pref.USE_TOR_PROXY, false);
} }
public boolean getUseI2pProxy() {
return mSharedPreferences.getBoolean(Pref.USE_I2P_PROXY, false);
}
public String getProxyHost() { public String getProxyHost() {
return mSharedPreferences.getString(Constants.Pref.PROXY_HOST, null); return mSharedPreferences.getString(Constants.Pref.PROXY_HOST, null);
} }
@ -285,36 +289,58 @@ public class Preferences {
} }
} }
public ProxyPrefs getProxyPrefs() { public ProxyPrefs.Category getProxyCategory() {
boolean useTor = getUseTorProxy(); boolean useTor = getUseTorProxy();
boolean useNormalProxy = getUseNormalProxy(); boolean useNormalProxy = getUseNormalProxy();
boolean useI2p = getUseI2pProxy();
if (useTor) { if (useI2p) return ProxyPrefs.Category.I2P;
return new ProxyPrefs(true, false, Constants.Orbot.PROXY_HOST, Constants.Orbot.PROXY_PORT, if (useTor) return ProxyPrefs.Category.TOR;
Constants.Orbot.PROXY_TYPE); if (useNormalProxy) return ProxyPrefs.Category.NORMAL;
return ProxyPrefs.Category.NONE;
} }
else if (useNormalProxy) {
return new ProxyPrefs(useTor, useNormalProxy, getProxyHost(), getProxyPort(), getProxyType()); public ProxyPrefs getProxyPrefs() {
} else { String proxyHost = null;
return new ProxyPrefs(false, false, null, -1, null); int proxyPort = -1;
Proxy.Type proxyType = null;
ProxyPrefs.Category category = getProxyCategory();
switch (category) {
case TOR:
proxyHost = Constants.Orbot.PROXY_HOST;
proxyPort = Constants.Orbot.PROXY_PORT;
proxyType = Constants.Orbot.PROXY_TYPE;
break;
case I2P:
proxyHost = Constants.I2p.PROXY_HOST;
proxyPort = Constants.I2p.PROXY_PORT;
proxyType = Constants.I2p.PROXY_TYPE;
break;
case NORMAL:
proxyHost = getProxyHost();
proxyPort = getProxyPort();
proxyType = getProxyType();
break;
// if NONE, do nothing, leave at default values
} }
return new ProxyPrefs(category, proxyHost, proxyPort, proxyType);
} }
public static class ProxyPrefs { public static class ProxyPrefs {
public final Category category;
public final ParcelableProxy parcelableProxy; public final ParcelableProxy parcelableProxy;
public final boolean torEnabled;
public final boolean normalPorxyEnabled; public enum Category {
TOR, I2P, NORMAL, NONE
}
/** /**
* torEnabled and normalProxyEnabled are not expected to both be true * a null proxy has category null
*
* @param torEnabled if Tor is to be used
* @param normalPorxyEnabled if user-specified proxy is to be used
*/ */
public ProxyPrefs(boolean torEnabled, boolean normalPorxyEnabled, String hostName, int port, Proxy.Type type) { public ProxyPrefs(Category catgeory, String hostName, int port, Proxy.Type type) {
this.torEnabled = torEnabled; this.category = catgeory;
this.normalPorxyEnabled = normalPorxyEnabled; if(category == Category.NONE) this.parcelableProxy = new ParcelableProxy(null, -1, null);
if(!torEnabled && !normalPorxyEnabled) this.parcelableProxy = new ParcelableProxy(null, -1, null);
else this.parcelableProxy = new ParcelableProxy(hostName, port, type); else this.parcelableProxy = new ParcelableProxy(hostName, port, type);
} }
} }

View File

@ -155,7 +155,7 @@ public class OrbotHelper {
} }
}; };
if (!proxyPrefs.torEnabled) { if (!(proxyPrefs.category == Preferences.ProxyPrefs.Category.TOR)) {
return true; return true;
} }

View File

@ -169,6 +169,8 @@
<!-- Proxy Preferences --> <!-- Proxy Preferences -->
<string name="pref_proxy_tor_title">"Enable Tor"</string> <string name="pref_proxy_tor_title">"Enable Tor"</string>
<string name="pref_proxy_tor_summary">"Requires Orbot to be installed"</string> <string name="pref_proxy_tor_summary">"Requires Orbot to be installed"</string>
<string name="pref_proxy_i2p_title">"Enable I2P"</string>
<string name="pref_proxy_i2p_summary">"Requires I2P to be installed"</string>
<string name="pref_proxy_normal_title">"Enable other proxy"</string> <string name="pref_proxy_normal_title">"Enable other proxy"</string>
<string name="pref_proxy_host_title">"Proxy Host"</string> <string name="pref_proxy_host_title">"Proxy Host"</string>
<string name="pref_proxy_host_err_invalid">"Proxy host cannot be empty"</string> <string name="pref_proxy_host_err_invalid">"Proxy host cannot be empty"</string>

View File

@ -5,6 +5,11 @@
android:persistent="true" android:persistent="true"
android:title="@string/pref_proxy_tor_title" android:title="@string/pref_proxy_tor_title"
android:summary="@string/pref_proxy_tor_summary" /> android:summary="@string/pref_proxy_tor_summary" />
<CheckBoxPreference
android:key="useI2pProxy"
android:persistent="true"
android:title="@string/pref_proxy_i2p_title"
android:summary="@string/pref_proxy_i2p_summary" />
<CheckBoxPreference <CheckBoxPreference
android:key="useNormalProxy" android:key="useNormalProxy"
android:persistent="true" android:persistent="true"