From 65ca77c3cbb5b8bece96e16ff4cd5040ad7884a3 Mon Sep 17 00:00:00 2001 From: Adithya Abraham Philip Date: Thu, 11 Jun 2015 01:34:35 +0530 Subject: orbot dialog fragments added --- .../keychain/ui/ImportKeysActivity.java | 40 +- .../keychain/ui/SettingsActivity.java | 419 ++++++++------------- .../keychain/ui/dialog/InstallDialogFragment.java | 143 +++++++ .../ui/dialog/OrbotStartDialogFragment.java | 99 +++++ .../ui/dialog/PreferenceInstallDialogFragment.java | 143 +++++++ .../keychain/util/ParcelableProxy.java | 5 + .../keychain/util/Preferences.java | 24 +- .../keychain/util/orbot/OrbotHelper.java | 155 ++++---- .../keychain/util/orbot/TorServiceUtils.java | 175 +++------ OpenKeychain/src/main/res/values/strings.xml | 29 +- OpenKeychain/src/main/res/xml/proxy_prefs.xml | 10 +- 11 files changed, 738 insertions(+), 504 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/InstallDialogFragment.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PreferenceInstallDialogFragment.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java index f78c19d13..b41ca58b4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java @@ -20,13 +20,13 @@ package org.sufficientlysecure.keychain.ui; import android.content.Intent; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.os.Message; import android.support.v4.app.Fragment; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; -import info.guardianproject.onionkit.ui.OrbotHelper; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.intents.OpenKeychainIntents; @@ -43,8 +43,8 @@ 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.util.ParcelableProxy; import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; import java.io.IOException; import java.net.Proxy; @@ -353,18 +353,33 @@ public class ImportKeysActivity extends BaseNfcActivity } } - public void loadCallback(ImportKeysListFragment.LoaderState loaderState) { + public void loadCallback(final ImportKeysListFragment.LoaderState loaderState) { if (loaderState instanceof ImportKeysListFragment.CloudLoaderState) { // do the tor check - OrbotHelper helper = new OrbotHelper(this); - // TODO: Add callbacks by modifying OrbotHelper so we know if the user wants to not use Tor + // this handle will set tor to be ignored whenever a message is received + Handler ignoreTorHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + // disables Tor until Activity is recreated + mProxyPrefs = new Preferences.ProxyPrefs(false, false, null, -1, null); + mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy); + } + }; + + if(mProxyPrefs.torEnabled && !OrbotHelper.isOrbotInstalled(this)) { + + OrbotHelper.getInstallDialogFragmentWithThirdButton( + new Messenger(ignoreTorHandler), + R.string.orbot_install_dialog_ignore_tor + ).show(getSupportFragmentManager(), "orbotInstallDialog"); - if(mProxyPrefs.torEnabled && !helper.isOrbotInstalled()) { - helper.promptToInstall(this); return; } - if(mProxyPrefs.torEnabled && !helper.isOrbotRunning()) { - helper.requestOrbotStart(this); + + if(mProxyPrefs.torEnabled && !OrbotHelper.isOrbotRunning()) { + OrbotHelper.getOrbotStartDialogFragment(new Messenger(ignoreTorHandler), + R.string.orbot_install_dialog_ignore_tor) + .show(getSupportFragmentManager(), "orbotStartDialog"); return; } } @@ -372,13 +387,6 @@ public class ImportKeysActivity extends BaseNfcActivity mListFragment.loadNew(loaderState, mProxyPrefs.parcelableProxy); } - /** - * disables use of Tor as proxy for this session - */ - private void disableTorForSession() { - mProxyPrefs = new Preferences.ProxyPrefs(false, false, null, -1, null); - } - private void handleMessage(Message message) { if (message.arg1 == ServiceProgressHandler.MessageStatus.OKAY.ordinal()) { // get returned data bundle diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java index 17df91ba6..6605995eb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/SettingsActivity.java @@ -18,6 +18,7 @@ package org.sufficientlysecure.keychain.ui; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -34,7 +35,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; -import info.guardianproject.onionkit.ui.OrbotHelper; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.AppCompatPreferenceActivity; @@ -42,6 +42,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; +import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; import java.util.List; @@ -49,6 +50,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity { public static final String ACTION_PREFS_CLOUD = "org.sufficientlysecure.keychain.ui.PREFS_CLOUD"; public static final String ACTION_PREFS_ADV = "org.sufficientlysecure.keychain.ui.PREFS_ADV"; + public static final String ACTION_PREFS_PROXY = "org.sufficientlysecure.keychain.ui.PREFS_PROXY"; public static final int REQUEST_CODE_KEYSERVER_PREF = 0x00007005; @@ -216,305 +218,202 @@ public class SettingsActivity extends AppCompatPreferenceActivity { } public static class ProxyPrefsFragment extends PreferenceFragment { - private CheckBoxPreference mUseTor; - private CheckBoxPreference mUseNormalProxy; - private EditTextPreference mProxyHost; - private EditTextPreference mProxyPort; - private ListPreference mProxyType; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // makes android's preference framework write to our file instead of default - // This allows us to use the "persistent" attribute to simplify code - sPreferences.setPreferenceManagerFileAndMode(getPreferenceManager()); - // Load the preferences from an XML resource - addPreferencesFromResource(R.xml.proxy_prefs); + new Initializer(this).initialize(); - mUseTor = (CheckBoxPreference) findPreference(Constants.Pref.USE_TOR_PROXY); - mUseNormalProxy = (CheckBoxPreference) findPreference(Constants.Pref.USE_NORMAL_PROXY); - mProxyHost = (EditTextPreference) findPreference(Constants.Pref.PROXY_HOST); - mProxyPort = (EditTextPreference) findPreference(Constants.Pref.PROXY_PORT); - mProxyType = (ListPreference) findPreference(Constants.Pref.PROXY_TYPE); + } - initializeUseTorPref(); - initializeUseNormalProxyPref(); - initializeEditTextPreferences(); - initializeProxyTypePreference(); + public static class Initializer { + private CheckBoxPreference mUseTor; + private CheckBoxPreference mUseNormalProxy; + private EditTextPreference mProxyHost; + private EditTextPreference mProxyPort; + private ListPreference mProxyType; + private PreferenceActivity mActivity; + private PreferenceFragment mFragment; + + public Initializer(PreferenceFragment fragment) { + mFragment = fragment; + } - if (mUseTor.isChecked()) disableNormalProxyPrefs(); - else if (mUseNormalProxy.isChecked()) disableUseTorPrefs(); - } + public Initializer(PreferenceActivity activity) { + mActivity = activity; + } - private void initializeUseTorPref() { - mUseTor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if ((Boolean)newValue) { - OrbotHelper orbotHelper = new OrbotHelper(ProxyPrefsFragment.this.getActivity()); - boolean installed = orbotHelper.isOrbotInstalled(); - if (!installed) { - Log.d(Constants.TAG, "Prompting to install Tor"); - orbotHelper.promptToInstall(ProxyPrefsFragment.this.getActivity()); - // don't let the user check the box until he's installed orbot - return false; - } else { - disableNormalProxyPrefs(); - // let the enable tor box be checked - return true; - } - } - else { - // we're unchecking Tor, so enable other proxy - enableNormalProxyPrefs(); - return true; - } + public Preference automaticallyFindPreference(String key) { + if(mFragment != null) { + return mFragment.findPreference(key); + } else { + return mActivity.findPreference(key); } - }); - } + } - private void initializeUseNormalProxyPref() { - mUseNormalProxy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if ((Boolean) newValue) { - disableUseTorPrefs(); - } else { - enableUseTorPrefs(); - } - return true; + public void initialize() { + // makes android's preference framework write to our file instead of default + // This allows us to use the "persistent" attribute to simplify code + if (mFragment != null) { + Preferences.setPreferenceManagerFileAndMode(mFragment.getPreferenceManager()); + // Load the preferences from an XML resource + mFragment.addPreferencesFromResource(R.xml.proxy_prefs); + } + else { + Preferences.setPreferenceManagerFileAndMode(mActivity.getPreferenceManager()); + // Load the preferences from an XML resource + mActivity.addPreferencesFromResource(R.xml.proxy_prefs); } - }); - } - private void initializeEditTextPreferences() { - mProxyHost.setSummary(mProxyHost.getText()); - mProxyPort.setSummary(mProxyPort.getText()); - - mProxyHost.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if (TextUtils.isEmpty((String) newValue)) { - Notify.create( - ProxyPrefsFragment.this.getActivity(), - R.string.pref_proxy_host_err_invalid, - Notify.Style.ERROR - ).show(); - return false; - } else { - mProxyHost.setSummary((CharSequence) newValue); - return true; + mUseTor = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_TOR_PROXY); + mUseNormalProxy = (CheckBoxPreference) automaticallyFindPreference(Constants.Pref.USE_NORMAL_PROXY); + mProxyHost = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_HOST); + mProxyPort = (EditTextPreference) automaticallyFindPreference(Constants.Pref.PROXY_PORT); + mProxyType = (ListPreference) automaticallyFindPreference(Constants.Pref.PROXY_TYPE); + initializeUseTorPref(); + initializeUseNormalProxyPref(); + initializeEditTextPreferences(); + initializeProxyTypePreference(); + + if (mUseTor.isChecked()) disableNormalProxyPrefs(); + else if (mUseNormalProxy.isChecked()) disableUseTorPrefs(); + } + + private void initializeUseTorPref() { + mUseTor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + Activity activity = mFragment != null ? mFragment.getActivity() : mActivity; + if ((Boolean)newValue) { + boolean installed = OrbotHelper.isOrbotInstalled(activity); + if (!installed) { + Log.d(Constants.TAG, "Prompting to install Tor"); + OrbotHelper.getPreferenceInstallDialogFragment().show(activity.getFragmentManager(), + "installDialog"); + // don't let the user check the box until he's installed orbot + return false; + } else { + disableNormalProxyPrefs(); + // let the enable tor box be checked + return true; + } + } + else { + // we're unchecking Tor, so enable other proxy + enableNormalProxyPrefs(); + return true; + } } - } - }); - - mProxyPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - try { - int port = Integer.parseInt((String) newValue); - if(port < 0 || port > 65535) { - Notify.create( - ProxyPrefsFragment.this.getActivity(), - R.string.pref_proxy_port_err_invalid, - Notify.Style.ERROR - ).show(); - return false; + }); + } + + private void initializeUseNormalProxyPref() { + mUseNormalProxy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + if ((Boolean) newValue) { + disableUseTorPrefs(); + } else { + enableUseTorPrefs(); } - // no issues, save port - mProxyPort.setSummary("" + port); return true; - } catch (NumberFormatException e) { - Notify.create( - ProxyPrefsFragment.this.getActivity(), - R.string.pref_proxy_port_err_invalid, - Notify.Style.ERROR - ).show(); - return false; } - } - }); - } - - private void initializeProxyTypePreference() { - mProxyType.setSummary(mProxyType.getEntry()); - - mProxyType.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - CharSequence entry = mProxyType.getEntries()[mProxyType.findIndexOfValue((String) newValue)]; - mProxyType.setSummary(entry); - return true; - } - }); - } - - private void disableNormalProxyPrefs() { - mUseNormalProxy.setChecked(false); - mUseNormalProxy.setEnabled(false); - mProxyHost.setEnabled(false); - mProxyPort.setEnabled(false); - mProxyType.setEnabled(false); - } - - private void enableNormalProxyPrefs() { - mUseNormalProxy.setEnabled(true); - mProxyHost.setEnabled(true); - mProxyPort.setEnabled(true); - mProxyType.setEnabled(true); - } - - private void disableUseTorPrefs() { - mUseTor.setChecked(false); - mUseTor.setEnabled(false); - } - - private void enableUseTorPrefs() { - mUseTor.setEnabled(true); - } - } - - @TargetApi(Build.VERSION_CODES.KITKAT) - public static class ProxyPrefsFragment extends PreferenceFragment { - private CheckBoxPreference mUseTor; - private CheckBoxPreference mUseNormalProxy; - private EditTextPreference mProxyHost; - private EditTextPreference mProxyPort; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Load the preferences from an XML resource - addPreferencesFromResource(R.xml.proxy_prefs); - - mUseTor = (CheckBoxPreference) findPreference(Constants.Pref.USE_TOR_PROXY); - mUseNormalProxy = (CheckBoxPreference) findPreference(Constants.Pref.USE_NORMAL_PROXY); - mProxyHost = (EditTextPreference) findPreference(Constants.Pref.PROXY_HOST); - mProxyPort = (EditTextPreference) findPreference(Constants.Pref.PROXY_PORT); - - initializeUseTorPref(); - initializeUseNormalProxyPref(); - initialiseEditTextPreferences(); + }); + } - if (mUseTor.isChecked()) disableNormalProxyPrefs(); - else if (mUseNormalProxy.isChecked()) disableUseTorPrefs(); - } + private void initializeEditTextPreferences() { + mProxyHost.setSummary(mProxyHost.getText()); + mProxyPort.setSummary(mProxyPort.getText()); - private void initializeUseTorPref() { - mUseTor.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if ((Boolean)newValue) { - OrbotHelper orbotHelper = new OrbotHelper(ProxyPrefsFragment.this.getActivity()); - boolean installed = orbotHelper.isOrbotInstalled(); - if (!installed) { - Log.d(Constants.TAG, "Prompting to install Tor"); - orbotHelper.promptToInstall(ProxyPrefsFragment.this.getActivity()); - // don't let the user check the box until he's installed orbot + mProxyHost.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + Activity activity = mFragment != null ? mFragment.getActivity() : mActivity; + if (TextUtils.isEmpty((String) newValue)) { + Notify.create( + activity, + R.string.pref_proxy_host_err_invalid, + Notify.Style.ERROR + ).show(); return false; } else { - disableNormalProxyPrefs(); - // let the enable tor box be checked + mProxyHost.setSummary((CharSequence) newValue); return true; } } - else { - // we're unchecking Tor, so enable other proxy - enableNormalProxyPrefs(); - return true; - } - } - }); - } - - private void initializeUseNormalProxyPref() { - mUseNormalProxy.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if ((Boolean) newValue) { - disableUseTorPrefs(); - } else { - enableUseTorPrefs(); - } - return true; - } - }); - } + }); - private void initialiseEditTextPreferences() { - mProxyHost.setSummary(mProxyHost.getText()); - mProxyPort.setSummary(mProxyPort.getText()); - - mProxyHost.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - if (newValue.equals("")) { - Notify.create( - ProxyPrefsFragment.this.getActivity(), - R.string.pref_proxy_host_err_invalid, - Notify.Style.ERROR - ).show(); - return false; - } else { - mProxyHost.setSummary((CharSequence) newValue); - return true; - } - } - }); - - mProxyPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - try { - int port = Integer.parseInt((String) newValue); - if(port < 0 || port > 65535) { + mProxyPort.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + Activity activity = mFragment != null ? mFragment.getActivity() : mActivity; + try { + int port = Integer.parseInt((String) newValue); + if(port < 0 || port > 65535) { + Notify.create( + activity, + R.string.pref_proxy_port_err_invalid, + Notify.Style.ERROR + ).show(); + return false; + } + // no issues, save port + mProxyPort.setSummary("" + port); + return true; + } catch (NumberFormatException e) { Notify.create( - ProxyPrefsFragment.this.getActivity(), + activity, R.string.pref_proxy_port_err_invalid, Notify.Style.ERROR ).show(); return false; } - // no issues, save port - mProxyPort.setSummary("" + port); + } + }); + } + + private void initializeProxyTypePreference() { + mProxyType.setSummary(mProxyType.getEntry()); + + mProxyType.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + CharSequence entry = mProxyType.getEntries()[mProxyType.findIndexOfValue((String) newValue)]; + mProxyType.setSummary(entry); return true; - } catch (NumberFormatException e) { - Notify.create( - ProxyPrefsFragment.this.getActivity(), - R.string.pref_proxy_port_err_invalid, - Notify.Style.ERROR - ).show(); - return false; } - } - }); - } + }); + } - private void disableNormalProxyPrefs() { - mUseNormalProxy.setChecked(false); - mUseNormalProxy.setEnabled(false); - mProxyHost.setEnabled(false); - mProxyPort.setEnabled(false); - } + private void disableNormalProxyPrefs() { + mUseNormalProxy.setChecked(false); + mUseNormalProxy.setEnabled(false); + mProxyHost.setEnabled(false); + mProxyPort.setEnabled(false); + mProxyType.setEnabled(false); + } - private void enableNormalProxyPrefs() { - mUseNormalProxy.setEnabled(true); - mProxyHost.setEnabled(true); - mProxyPort.setEnabled(true); - } + private void enableNormalProxyPrefs() { + mUseNormalProxy.setEnabled(true); + mProxyHost.setEnabled(true); + mProxyPort.setEnabled(true); + mProxyType.setEnabled(true); + } - private void disableUseTorPrefs() { - mUseTor.setChecked(false); - mUseTor.setEnabled(false); - } + private void disableUseTorPrefs() { + mUseTor.setChecked(false); + mUseTor.setEnabled(false); + } - private void enableUseTorPrefs() { - mUseTor.setEnabled(true); + private void enableUseTorPrefs() { + mUseTor.setEnabled(true); + } } + } + @TargetApi(Build.VERSION_CODES.KITKAT) protected boolean isValidFragment(String fragmentName) { return AdvancedPrefsFragment.class.getName().equals(fragmentName) || CloudSearchPrefsFragment.class.getName().equals(fragmentName) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/InstallDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/InstallDialogFragment.java new file mode 100644 index 000000000..01ff4715d --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/InstallDialogFragment.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui.dialog; + +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +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 InstallDialogFragment extends DialogFragment { + private static final String ARG_MESSENGER = "messenger"; + private static final String ARG_TITLE = "title"; + private static final String ARG_MESSAGE = "message"; + private static final String ARG_MIDDLE_BUTTON = "middleButton"; + private static final String ARG_INSTALL_PATH = "installPath"; + private static final String ARG_USE_MIDDLE_BUTTON = "useMiddleButton"; + + public static final String PLAY_STORE_PATH = "market://search?q=pname:"; + + public static final int MESSAGE_MIDDLE_CLICKED = 1; + + /** + * Creates a dialog which prompts the user to install an application. Consists of two default buttons ("Install" + * and "Cancel") and an optional third button. Callbacks are provided only for the middle button, if set. + * + * @param messenger required only for callback from middle button if it has been set + * @param title + * @param message content of dialog + * @param packageToInstall package name of application to install + * @param middleButton if not null, adds a third button to the app with a call back + * @return The dialog to display + */ + public static InstallDialogFragment newInstance(Messenger messenger, int title, int message, + String packageToInstall, int middleButton, boolean useMiddleButton) { + InstallDialogFragment frag = new InstallDialogFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_MESSENGER, messenger); + + args.putInt(ARG_TITLE, title); + args.putInt(ARG_MESSAGE, message); + args.putInt(ARG_MIDDLE_BUTTON, middleButton); + args.putString(ARG_INSTALL_PATH, PLAY_STORE_PATH + packageToInstall); + args.putBoolean(ARG_USE_MIDDLE_BUTTON, useMiddleButton); + + frag.setArguments(args); + + return frag; + } + + /** + * To create a DialogFragment with only two buttons + * + * @param title + * @param message + * @param packageToInstall + * @return + */ + public static InstallDialogFragment newInstance(int title, int message, + String packageToInstall) { + return newInstance(null, title, message, packageToInstall, -1, false); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Activity activity = getActivity(); + + final Messenger messenger = getArguments().getParcelable(ARG_MESSENGER); + + final int title = getArguments().getInt(ARG_TITLE); + final int message = getArguments().getInt(ARG_MESSAGE); + final int middleButton = getArguments().getInt(ARG_MIDDLE_BUTTON); + final String installPath = getArguments().getString(ARG_INSTALL_PATH); + final boolean useMiddleButton = getArguments().getBoolean(ARG_USE_MIDDLE_BUTTON); + + CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(activity); + + builder.setTitle(title).setMessage(message); + + builder.setNegativeButton(R.string.orbot_install_dialog_cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + + builder.setPositiveButton(R.string.orbot_install_dialog_install, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Uri uri = Uri.parse(installPath); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + activity.startActivity(intent); + } + } + ); + + if (useMiddleButton) { + builder.setNeutralButton(middleButton, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Message msg = new Message(); + msg.what=MESSAGE_MIDDLE_CLICKED; + try { + messenger.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); + } + } + } + ); + } + + return builder.show(); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java new file mode 100644 index 000000000..e9092b14a --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/OrbotStartDialogFragment.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * + * 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 . + */ + + +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; +import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; + +/** + * displays a dialog asking the user to enable Tor + */ +public class OrbotStartDialogFragment extends DialogFragment { + private static final String ARG_MESSENGER = "messenger"; + private static final String ARG_TITLE = "title"; + private static final String ARG_MESSAGE = "message"; + private static final String ARG_MIDDLE_BUTTON = "middleButton"; + + public static final int MESSAGE_MIDDLE_BUTTON = 1; + + public static OrbotStartDialogFragment newInstance(Messenger messenger, int title, int message, int middleButton) { + Bundle args = new Bundle(); + args.putParcelable(ARG_MESSENGER, messenger); + args.putInt(ARG_TITLE, title); + args.putInt(ARG_MESSAGE, message); + args.putInt(ARG_MIDDLE_BUTTON, middleButton); + + OrbotStartDialogFragment fragment = new OrbotStartDialogFragment(); + fragment.setArguments(args); + + return fragment; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + + final Messenger messenger = getArguments().getParcelable(ARG_MESSENGER); + int title = getArguments().getInt(ARG_TITLE); + final int message = getArguments().getInt(ARG_MESSAGE); + int middleButton = getArguments().getInt(ARG_MIDDLE_BUTTON); + + CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(getActivity()); + builder.setTitle(title).setMessage(message); + + builder.setNegativeButton(R.string.orbot_start_dialog_cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + + builder.setPositiveButton(R.string.orbot_start_dialog_start, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + getActivity().startActivityForResult(OrbotHelper.getOrbotStartIntent(), 1); + } + }); + + builder.setNeutralButton(middleButton, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Message msg = new Message(); + msg.what = MESSAGE_MIDDLE_BUTTON; + try { + messenger.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); + } + } + }); + + return builder.show(); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PreferenceInstallDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PreferenceInstallDialogFragment.java new file mode 100644 index 000000000..8236ff9d7 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/PreferenceInstallDialogFragment.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012-2014 Dominik Schürmann + * + * 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 . + */ + +package org.sufficientlysecure.keychain.ui.dialog; + +import android.app.Activity; +import android.app.Dialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; +import android.app.DialogFragment; +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.util.Log; + +public class PreferenceInstallDialogFragment extends DialogFragment { + private static final String ARG_MESSENGER = "messenger"; + private static final String ARG_TITLE = "title"; + private static final String ARG_MESSAGE = "message"; + private static final String ARG_MIDDLE_BUTTON = "middleButton"; + private static final String ARG_INSTALL_PATH = "installPath"; + private static final String ARG_USE_MIDDLE_BUTTON = "installPath"; + + public static final String PLAY_STORE_PATH = "market://search?q=pname:"; + + public static final int MESSAGE_MIDDLE_CLICKED = 1; + + /** + * Creates a dialog which prompts the user to install an application. Consists of two default buttons ("Install" + * and "Cancel") and an optional third button. Callbacks are provided only for the middle button, if set. + * + * @param messenger required only for callback from middle button if it has been set + * @param title + * @param message content of dialog + * @param packageToInstall package name of application to install + * @param middleButton if not null, adds a third button to the app with a call back + * @return The dialog to display + */ + public static PreferenceInstallDialogFragment newInstance(Messenger messenger, int title, int message, + String packageToInstall, int middleButton, boolean useMiddleButton) { + PreferenceInstallDialogFragment frag = new PreferenceInstallDialogFragment(); + Bundle args = new Bundle(); + args.putParcelable(ARG_MESSENGER, messenger); + + args.putInt(ARG_TITLE, title); + args.putInt(ARG_MESSAGE, message); + args.putInt(ARG_MIDDLE_BUTTON, middleButton); + args.putString(ARG_INSTALL_PATH, PLAY_STORE_PATH + packageToInstall); + args.putBoolean(ARG_USE_MIDDLE_BUTTON, useMiddleButton); + + frag.setArguments(args); + + return frag; + } + + /** + * To create a DialogFragment with only two buttons + * + * @param title + * @param message + * @param packageToInstall + * @return + */ + public static PreferenceInstallDialogFragment newInstance(int title, int message, + String packageToInstall) { + return newInstance(null, title, message, packageToInstall, -1, false); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Activity activity = getActivity(); + + final Messenger messenger = getArguments().getParcelable(ARG_MESSENGER); + + final String title = getArguments().getString(ARG_TITLE); + final String message = getArguments().getString(ARG_MESSAGE); + final String installPath = getArguments().getString(ARG_INSTALL_PATH); + final String middleButton = getArguments().getString(ARG_MIDDLE_BUTTON); + final boolean useMiddleButton = getArguments().getBoolean(ARG_USE_MIDDLE_BUTTON); + + CustomAlertDialogBuilder builder = new CustomAlertDialogBuilder(activity); + + builder.setTitle(title).setMessage(message); + + builder.setNegativeButton(R.string.orbot_install_dialog_cancel, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + + builder.setPositiveButton(R.string.orbot_install_dialog_install, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Uri uri = Uri.parse(installPath); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + activity.startActivity(intent); + } + } + ); + + if (useMiddleButton) { + builder.setNeutralButton(middleButton, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + Message msg = new Message(); + msg.what=MESSAGE_MIDDLE_CLICKED; + try { + messenger.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); + } + } + } + ); + } + + return builder.show(); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableProxy.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableProxy.java index e5bb1deb4..601547fa9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableProxy.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ParcelableProxy.java @@ -36,6 +36,9 @@ public class ParcelableProxy implements Parcelable { public ParcelableProxy(String hostName, int port, Proxy.Type type) { mProxyHost = hostName; + + if (hostName == null) return; // represents a null proxy + mProxyPort = port; switch (type) { @@ -51,6 +54,8 @@ public class ParcelableProxy implements Parcelable { } public Proxy getProxy() { + if(mProxyHost == null) return null; + Proxy.Type type = null; switch (mProxyType) { case TYPE_HTTP: diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java index 5650a7deb..f54eac867 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/Preferences.java @@ -23,12 +23,10 @@ import android.content.SharedPreferences; import android.content.res.Resources; import android.preference.PreferenceManager; -import info.guardianproject.onionkit.ui.OrbotHelper; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants.Pref; import org.sufficientlysecure.keychain.R; -import java.net.InetSocketAddress; import java.net.Proxy; import java.util.ArrayList; import java.util.Arrays; @@ -65,7 +63,7 @@ public class Preferences { updateSharedPreferences(context); } - public void setPreferenceManagerFileAndMode(PreferenceManager manager) { + public static void setPreferenceManagerFileAndMode(PreferenceManager manager) { manager.setSharedPreferencesName(PREF_FILE_NAME); manager.setSharedPreferencesMode(PREF_FILE_MODE); } @@ -249,32 +247,14 @@ public class Preferences { return mSharedPreferences.getBoolean(Constants.Pref.USE_NORMAL_PROXY, false); } - public void setUseNormalProxy(boolean use) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Constants.Pref.USE_NORMAL_PROXY, use); - editor.commit(); - } - public boolean getUseTorProxy() { return mSharedPreferences.getBoolean(Constants.Pref.USE_TOR_PROXY, false); } - public void setUseTorProxy(boolean use) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putBoolean(Constants.Pref.USE_TOR_PROXY, use); - editor.commit(); - } - public String getProxyHost() { return mSharedPreferences.getString(Constants.Pref.PROXY_HOST, null); } - public void setProxyHost(String host) { - SharedPreferences.Editor editor = mSharedPreferences.edit(); - editor.putString(Constants.Pref.PROXY_HOST, host); - editor.commit(); - } - /** * we store port as String for easy interfacing with EditTextPreference, but return it as an integer * @@ -338,7 +318,7 @@ public class Preferences { public ProxyPrefs(boolean torEnabled, boolean normalPorxyEnabled, String hostName, int port, Proxy.Type type) { this.torEnabled = torEnabled; this.normalPorxyEnabled = normalPorxyEnabled; - if(!torEnabled && !normalPorxyEnabled) this.parcelableProxy = null; + if(!torEnabled && !normalPorxyEnabled) this.parcelableProxy = new ParcelableProxy(null, -1, null); else this.parcelableProxy = new ParcelableProxy(hostName, port, type); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java index d9566be4a..fb016f9e6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/OrbotHelper.java @@ -1,5 +1,53 @@ +/* This is the license for Orlib, a free software project to + provide anonymity on the Internet from a Google Android smartphone. -package info.guardianproject.onionkit.ui; + For more information about Orlib, see https://guardianproject.info/ + + If you got this file as a part of a larger bundle, there may be other + license terms that you should be aware of. + =============================================================================== + Orlib is distributed under this license (aka the 3-clause BSD license) + + Copyright (c) 2009-2010, Nathan Freitas, The Guardian Project + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + * Neither the names of the copyright owners nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + ***** + Orlib contains a binary distribution of the JSocks library: + http://code.google.com/p/jsocks-mirror/ + which is licensed under the GNU Lesser General Public License: + http://www.gnu.org/licenses/lgpl.html + + ***** +*/ + +package org.sufficientlysecure.keychain.util.orbot; import android.app.Activity; import android.app.AlertDialog; @@ -7,42 +55,37 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; -import android.net.Uri; - -import info.guardianproject.onionkit.R; - +import android.os.Messenger; +import android.support.v4.app.DialogFragment; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.dialog.InstallDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.OrbotStartDialogFragment; +import org.sufficientlysecure.keychain.ui.dialog.PreferenceInstallDialogFragment; + +/** + * This class is taken from the NetCipher library: https://github.com/guardianproject/NetCipher/ + */ public class OrbotHelper { - private final static int REQUEST_CODE_STATUS = 100; - public final static String ORBOT_PACKAGE_NAME = "org.torproject.android"; public final static String TOR_BIN_PATH = "/data/data/org.torproject.android/app_bin/tor"; public final static String ACTION_START_TOR = "org.torproject.android.START_TOR"; - public final static String ACTION_REQUEST_HS = "org.torproject.android.REQUEST_HS_PORT"; - public final static int HS_REQUEST_CODE = 9999; - - private Context mContext = null; - - public OrbotHelper(Context context) - { - mContext = context; - } - public boolean isOrbotRunning() + public static boolean isOrbotRunning() { int procId = TorServiceUtils.findProcessId(TOR_BIN_PATH); return (procId != -1); } - public boolean isOrbotInstalled() + public static boolean isOrbotInstalled(Context context) { - return isAppInstalled(ORBOT_PACKAGE_NAME); + return isAppInstalled(ORBOT_PACKAGE_NAME, context); } - private boolean isAppInstalled(String uri) { - PackageManager pm = mContext.getPackageManager(); + private static boolean isAppInstalled(String uri, Context context) { + PackageManager pm = context.getPackageManager(); boolean installed = false; try { pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES); @@ -53,66 +96,32 @@ public class OrbotHelper { return installed; } - public void promptToInstall(Activity activity) + /** + * hack to get around teh fact that PreferenceActivity still supports only android.app.DialogFragment + * + * @return + */ + public static android.app.DialogFragment getPreferenceInstallDialogFragment() { - String uriMarket = activity.getString(R.string.market_orbot); - // show dialog - install from market, f-droid or direct APK - showDownloadDialog(activity, activity.getString(R.string.install_orbot_), - activity.getString(R.string.you_must_have_orbot), - activity.getString(R.string.yes), activity.getString(R.string.no), uriMarket); + return PreferenceInstallDialogFragment.newInstance(R.string.orbot_install_dialog_title, + R.string.orbot_install_dialog_content, ORBOT_PACKAGE_NAME); } - private static AlertDialog showDownloadDialog(final Activity activity, - CharSequence stringTitle, CharSequence stringMessage, CharSequence stringButtonYes, - CharSequence stringButtonNo, final String uriString) { - AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity); - downloadDialog.setTitle(stringTitle); - downloadDialog.setMessage(stringMessage); - downloadDialog.setPositiveButton(stringButtonYes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - Uri uri = Uri.parse(uriString); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - activity.startActivity(intent); - } - }); - downloadDialog.setNegativeButton(stringButtonNo, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - } - }); - return downloadDialog.show(); - } - - public void requestOrbotStart(final Activity activity) + public static DialogFragment getInstallDialogFragment() { - - AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity); - downloadDialog.setTitle(R.string.start_orbot_); - downloadDialog - .setMessage(R.string.orbot_doesn_t_appear_to_be_running_would_you_like_to_start_it_up_and_connect_to_tor_); - downloadDialog.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - activity.startActivityForResult(getOrbotStartIntent(), 1); - } - }); - downloadDialog.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - } - }); - downloadDialog.show(); - + return InstallDialogFragment.newInstance(R.string.orbot_install_dialog_title, + R.string.orbot_install_dialog_content, ORBOT_PACKAGE_NAME); } - public void requestHiddenServiceOnPort(Activity activity, int port) + public static DialogFragment getInstallDialogFragmentWithThirdButton(Messenger messenger, int middleButton) { - Intent intent = new Intent(ACTION_REQUEST_HS); - intent.setPackage(ORBOT_PACKAGE_NAME); - intent.putExtra("hs_port", port); + return InstallDialogFragment.newInstance(messenger, R.string.orbot_install_dialog_title, + R.string.orbot_install_dialog_content, ORBOT_PACKAGE_NAME, middleButton, true); + } - activity.startActivityForResult(intent, HS_REQUEST_CODE); + public static DialogFragment getOrbotStartDialogFragment(Messenger messenger, int middleButton) { + return OrbotStartDialogFragment.newInstance(messenger, R.string.orbot_start_dialog_title, R.string.orbot_start_dialog_content, + middleButton); } public static Intent getOrbotStartIntent() { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/TorServiceUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/TorServiceUtils.java index 80a812344..127e9d43f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/TorServiceUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/orbot/TorServiceUtils.java @@ -1,85 +1,72 @@ -/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ -/* See LICENSE for licensing information */ +/* This is the license for Orlib, a free software project to + provide anonymity on the Internet from a Google Android smartphone. -package info.guardianproject.onionkit.ui; + For more information about Orlib, see https://guardianproject.info/ -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.URLEncoder; -import java.util.StringTokenizer; + If you got this file as a part of a larger bundle, there may be other + license terms that you should be aware of. + =============================================================================== + Orlib is distributed under this license (aka the 3-clause BSD license) -import android.util.Log; + Copyright (c) 2009-2010, Nathan Freitas, The Guardian Project -public class TorServiceUtils { + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: - private final static String TAG = "TorUtils"; - // various console cmds - public final static String SHELL_CMD_CHMOD = "chmod"; - public final static String SHELL_CMD_KILL = "kill -9"; - public final static String SHELL_CMD_RM = "rm"; - public final static String SHELL_CMD_PS = "ps"; - public final static String SHELL_CMD_PIDOF = "pidof"; + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. - public final static String CHMOD_EXE_VALUE = "700"; + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. - public static boolean isRootPossible() - { + * Neither the names of the copyright owners nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. - StringBuilder log = new StringBuilder(); + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - try { + ***** + Orlib contains a binary distribution of the JSocks library: + http://code.google.com/p/jsocks-mirror/ + which is licensed under the GNU Lesser General Public License: + http://www.gnu.org/licenses/lgpl.html - // Check if Superuser.apk exists - File fileSU = new File("/system/app/Superuser.apk"); - if (fileSU.exists()) - return true; + ***** +*/ - fileSU = new File("/system/app/superuser.apk"); - if (fileSU.exists()) - return true; +package org.sufficientlysecure.keychain.util.orbot; - fileSU = new File("/system/bin/su"); - if (fileSU.exists()) - { - String[] cmd = { - "su" - }; - int exitCode = TorServiceUtils.doShellCommand(cmd, log, false, true); - if (exitCode != 0) - return false; - else - return true; - } - - // Check for 'su' binary - String[] cmd = { - "which su" - }; - int exitCode = TorServiceUtils.doShellCommand(cmd, log, false, true); - - if (exitCode == 0) { - Log.d(TAG, "root exists, but not sure about permissions"); - return true; - - } +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStreamReader; +import java.net.URLEncoder; +import java.util.StringTokenizer; - } catch (IOException e) { - // this means that there is no root to be had (normally) so we won't - // log anything - Log.e(TAG, "Error checking for root access", e); +import android.util.Log; - } catch (Exception e) { - Log.e(TAG, "Error checking for root access", e); - // this means that there is no root to be had (normally) - } +/** + * This class is taken from the NetCipher library: https://github.com/guardianproject/NetCipher/ + */ - Log.e(TAG, "Could not acquire root permissions"); +public class TorServiceUtils { - return false; - } + private final static String TAG = "TorUtils"; + // various console cmds + public final static String SHELL_CMD_PS = "ps"; + public final static String SHELL_CMD_PIDOF = "pidof"; public static int findProcessId(String command) { @@ -175,60 +162,4 @@ public class TorServiceUtils { return procId; } - - public static int doShellCommand(String[] cmds, StringBuilder log, boolean runAsRoot, - boolean waitFor) throws Exception - { - - Process proc = null; - int exitCode = -1; - - if (runAsRoot) - proc = Runtime.getRuntime().exec("su"); - else - proc = Runtime.getRuntime().exec("sh"); - - OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream()); - - for (int i = 0; i < cmds.length; i++) - { - // TorService.logMessage("executing shell cmd: " + cmds[i] + - // "; runAsRoot=" + runAsRoot + ";waitFor=" + waitFor); - - out.write(cmds[i]); - out.write("\n"); - } - - out.flush(); - out.write("exit\n"); - out.flush(); - - if (waitFor) - { - - final char buf[] = new char[10]; - - // Consume the "stdout" - InputStreamReader reader = new InputStreamReader(proc.getInputStream()); - int read = 0; - while ((read = reader.read(buf)) != -1) { - if (log != null) - log.append(buf, 0, read); - } - - // Consume the "stderr" - reader = new InputStreamReader(proc.getErrorStream()); - read = 0; - while ((read = reader.read(buf)) != -1) { - if (log != null) - log.append(buf, 0, read); - } - - exitCode = proc.waitFor(); - - } - - return exitCode; - - } } diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index d1380c4fe..12d222e6a 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -174,21 +174,38 @@ "Search keys on keybase.io" - "Enable Tor" + "Enable Tor" "Requires Orbot to be installed" - "Enable other proxy" - "Proxy Host" + "Enable other proxy" + "Proxy Host" "Proxy host cannot be empty" - "Proxy Port" + "Proxy Port" "Invalid port number entered" - "Proxy Type" + "Proxy Type" - + "HTTP" "SOCKS" "proxyHttp" "proxySocks" + + + Install Orbot to use Tor? + "Install" + You must have Orbot installed and activated to proxy traffic through it. Would you like to install it? + "Cancel" + "Don\'t use Tor" + + + Start Orbot? + "Orbot doesn\'t appear to be running. Would you like to start it up and connect to Tor?" + "Start Orbot" + "Start Orbot" + "Cancel" + "Don\'t use Tor" + + "<no name>" "<none>" diff --git a/OpenKeychain/src/main/res/xml/proxy_prefs.xml b/OpenKeychain/src/main/res/xml/proxy_prefs.xml index ab9c5a3e3..94e101cb6 100644 --- a/OpenKeychain/src/main/res/xml/proxy_prefs.xml +++ b/OpenKeychain/src/main/res/xml/proxy_prefs.xml @@ -3,17 +3,17 @@ + android:title="@string/pref_proxy_normal_title" /> @@ -21,7 +21,7 @@ android:key="proxyPort" android:defaultValue="8118" android:persistent="true" - android:title="@string/pref_proxy_port_label" + android:title="@string/pref_proxy_port_title" android:textCursorDrawable="@null" android:inputType="number" /> + android:title="@string/pref_proxy_type_title" /> -- cgit v1.2.3