diff --git a/AUTHORS b/AUTHORS index f99ac6f9..135d9b46 100644 --- a/AUTHORS +++ b/AUTHORS @@ -27,7 +27,7 @@ provided guidance in the entire effort. Adam Langley made the original valiant effort to port Tor to Android. -Sathyanarayanan created a patch for the wizard +Sathyanarayanan created a patch for the wizard which updated the icon and link for the secure chat app info to point to Gibberbot, and hopefully will continue to contribute useful patches. diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 4876f402..d0775580 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -5,7 +5,7 @@ - + diff --git a/res/drawable/icon_firefox.png b/res/drawable/icon_firefox.png new file mode 100644 index 00000000..27b0cf48 Binary files /dev/null and b/res/drawable/icon_firefox.png differ diff --git a/res/drawable/icon_orweb.png b/res/drawable/icon_orweb.png deleted file mode 100755 index 679986f3..00000000 Binary files a/res/drawable/icon_orweb.png and /dev/null differ diff --git a/res/drawable/icon_otrchat.png b/res/drawable/icon_otrchat.png deleted file mode 100755 index 08171aba..00000000 Binary files a/res/drawable/icon_otrchat.png and /dev/null differ diff --git a/res/drawable/proxymob.png b/res/drawable/proxymob.png new file mode 100644 index 00000000..6e232194 Binary files /dev/null and b/res/drawable/proxymob.png differ diff --git a/res/drawable/warning.png b/res/drawable/warning.png new file mode 100644 index 00000000..42dc6d66 Binary files /dev/null and b/res/drawable/warning.png differ diff --git a/res/layout/layout_apps_item.xml b/res/layout/layout_apps_item.xml index 49939644..9d16efdd 100644 --- a/res/layout/layout_apps_item.xml +++ b/res/layout/layout_apps_item.xml @@ -5,12 +5,13 @@ android:layout_height="fill_parent" android:stretchColumns="1"> - + + diff --git a/res/layout/layout_wizard_permissions.xml b/res/layout/layout_wizard_permissions.xml new file mode 100644 index 00000000..1ba5fec1 --- /dev/null +++ b/res/layout/layout_wizard_permissions.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/layout_wizard_root.xml b/res/layout/layout_wizard_root.xml index f71c284a..530d917c 100644 --- a/res/layout/layout_wizard_root.xml +++ b/res/layout/layout_wizard_root.xml @@ -1,29 +1,69 @@ - + android:layout_height="fill_parent"> + + + + + + + + + + - + + - - - - - - - + + + + + diff --git a/res/layout/layout_wizard_tips.xml b/res/layout/layout_wizard_tips.xml index 19aaef06..17ddb88d 100644 --- a/res/layout/layout_wizard_tips.xml +++ b/res/layout/layout_wizard_tips.xml @@ -1,29 +1,63 @@ - + android:layout_height="fill_parent"> + + + + + + + + + + - + + + android:paddingRight="20dip" + > - + + + + + + diff --git a/res/layout/scrollingtext_buttons_view.xml b/res/layout/scrollingtext_buttons_view.xml new file mode 100644 index 00000000..df599220 --- /dev/null +++ b/res/layout/scrollingtext_buttons_view.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 1a5daf3f..6a82430b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -130,9 +130,32 @@ General Start Orbot on Boot Automatically start Orbot and connect Tor when your Android device boots - - Tor Tethering + + + Orbot brings Tor to Android \n\nTor helps you defend against a form of network surveillance that threatens privacy, confidential business activity and relationships, and state security known as traffic analysis + + Warning + Simply installing Orbot will not automatically anonymize your mobile traffic.\n\nPlease follow the following steps to get started + + Permissions + Orbot has detected that you have root permissions enabled. To enable \'Transparent Proxying\', please grant superuser privileges to Orbot + If you choose to continue without providing superuser privileges, make sure to use apps made to work with orbot + Orbot has detected that you do not have root permissions.\nTransparent Proxying is not possible without superuser privileges.\nMake sure to use apps that have been configured to work with Orbot + + Orbot configured Apps + Gibberbot - Secure instant messaging client for Android + Firefox - Android browser - To be used along with ProxyMob Add-on + ProxyMob - Simple Firefox Add-on for setting HTTP, SOCKS and SSL proxy settings + https://market.android.com/details?id=info.guardianproject.otr.app.im + https://market.android.com/details?id=org.mozilla.firefox + https://addons.mozilla.org/mobile/downloads/latest/251558/type:attachment/addon-251558-latest.xpi?src=addon-detail + + Transparent Proxy + Transparent Proxying allows you to redirect client requests without any special configuration or knowledge at the client. + (Check this box if you have no idea what we are talking about) + None + + Tor Tethering Enable Tor Transparent Proxying for Wifi and USB Tethered Devices - - + diff --git a/res/values/theme.xml b/res/values/theme.xml new file mode 100644 index 00000000..efc15c45 --- /dev/null +++ b/res/values/theme.xml @@ -0,0 +1,9 @@ + + + + #333 + + diff --git a/src/org/torproject/android/ConfigureTransProxy.java b/src/org/torproject/android/ConfigureTransProxy.java new file mode 100644 index 00000000..d515aaed --- /dev/null +++ b/src/org/torproject/android/ConfigureTransProxy.java @@ -0,0 +1,183 @@ +package org.torproject.android; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.net.Uri; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.Toast; + +public class ConfigureTransProxy extends Activity implements TorConstants { + + private Context context; + private int flag = 0; + + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + context = this; + + } + + @Override + protected void onStart() { + + super.onStart(); + setContentView(R.layout.layout_wizard_root); + + stepSix(); + + } + + @Override + protected void onResume() { + super.onResume(); + + + } + + + + private void stepSix(){ + + String title = context.getString(R.string.wizard_transproxy_title); + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + Button back = ((Button)findViewById(R.id.btnWizard1)); + Button next = ((Button)findViewById(R.id.btnWizard2)); + next.setEnabled(false); + + back.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + startActivityForResult(new Intent(getBaseContext(), Permissions.class), 1); + } + }); + + next.setOnClickListener(new View.OnClickListener() { + + //Dirty flag variable - improve logic + @Override + public void onClick(View v) { + if( flag == 1 ) + context.startActivity(new Intent(context, AppManager.class)); + + else + showWizardFinal(); + } + }); + + RadioGroup mRadioGroup = (RadioGroup)findViewById(R.id.radioGroup); + mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener (){ + + + @Override + public void onCheckedChanged(RadioGroup group, int checkedId){ + Button next = ((Button)findViewById(R.id.btnWizard2)); + next.setEnabled(true); + next.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + showWizardFinal(); + } + }); + + RadioButton rb0 = (RadioButton)findViewById(R.id.radio0); + RadioButton rb1 = (RadioButton)findViewById(R.id.radio1); + RadioButton rb2 = (RadioButton)findViewById(R.id.radio2); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + Editor pEdit = prefs.edit(); + pEdit.putBoolean(PREF_TRANSPARENT, rb0.isChecked()); + pEdit.putBoolean(PREF_TRANSPARENT_ALL, rb0.isChecked()); + pEdit.commit(); + + if(rb0.isChecked()) + { + pEdit.putString("radiobutton","rb0"); + pEdit.commit(); + } + + else if(rb1.isChecked()) + { + flag = 1; + + pEdit.putBoolean(PREF_TRANSPARENT, true); + pEdit.putBoolean(PREF_TRANSPARENT_ALL, false); + pEdit.putString("radiobutton","rb1"); + pEdit.commit(); + + next.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + context.startActivity(new Intent(context, AppManager.class)); + + + } + }); + } + else if(rb2.isChecked()) + { + pEdit.putString("radiobutton", "rb2"); + pEdit.commit(); + } + + } + }); + + + } + + private void showWizardFinal () + { + String title = null; + String msg = null; + + + title = context.getString(R.string.wizard_final); + msg = context.getString(R.string.wizard_final_msg); + + DialogInterface.OnClickListener ocListener = new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + context.startActivity(new Intent(context, Orbot.class)); + + } + }; + + + new AlertDialog.Builder(context) + .setIcon(R.drawable.icon) + .setTitle(title) + .setPositiveButton(R.string.button_close, ocListener) + .setMessage(msg) + .show(); + + + + + } +} \ No newline at end of file diff --git a/src/org/torproject/android/LotsaText.java b/src/org/torproject/android/LotsaText.java new file mode 100644 index 00000000..1b0656b6 --- /dev/null +++ b/src/org/torproject/android/LotsaText.java @@ -0,0 +1,133 @@ +package org.torproject.android; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.view.View; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +public class LotsaText extends Activity implements TorConstants{ + + private Context context; + + protected void onCreate(Bundle savedInstanceState) + { + + + super.onCreate(savedInstanceState); + context = this; + + + } + + @Override + protected void onStart() { + + super.onStart(); + setContentView(R.layout.scrollingtext_buttons_view); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + boolean wizardScreen1 = prefs.getBoolean("wizardscreen1",true); + if(wizardScreen1) + stepOne(); + else + stepTwo(); + + } + + @Override + protected void onResume() { + super.onResume(); + + + } + + + + private void stepOne() { + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + Editor pEdit = prefs.edit(); + pEdit.putBoolean("wizardscreen1",true); + pEdit.commit(); + + String title = context.getString(R.string.wizard_title); + String msg = context.getString(R.string.wizard_title_msg); + + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + TextView txtBody = ((TextView)findViewById(R.id.WizardTextBody)); + txtBody.setText(msg); + + Button btn1 = ((Button)findViewById(R.id.btnWizard1)); + Button btn2 = ((Button)findViewById(R.id.btnWizard2)); + ImageView img = (ImageView) findViewById(R.id.orbot_image); + + btn1.setVisibility(Button.INVISIBLE); + img.setImageResource(R.drawable.tor); + + btn2.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + stepTwo(); + } + }); + + } + + private void stepTwo() { + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + Editor pEdit = prefs.edit(); + pEdit.putBoolean("wizardscreen1",false); + pEdit.commit(); + + setContentView(R.layout.scrollingtext_buttons_view); + String title = context.getString(R.string.wizard_warning_title); + String msg = context.getString(R.string.wizard_warning_msg); + + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + TextView txtBody = ((TextView)findViewById(R.id.WizardTextBody)); + txtBody.setText(msg); + + Button btn1 = ((Button)findViewById(R.id.btnWizard1)); + Button btn2 = ((Button)findViewById(R.id.btnWizard2)); + ImageView img = (ImageView) findViewById(R.id.orbot_image); + + btn1.setVisibility(Button.VISIBLE); + img.setImageResource(R.drawable.warning); + + btn1.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + stepOne(); + } + }); + + btn2.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + startActivityForResult(new Intent(getBaseContext(), Permissions.class), 1); + } + }); + + } + + +} \ No newline at end of file diff --git a/src/org/torproject/android/Orbot.java b/src/org/torproject/android/Orbot.java index 690ce108..73748221 100644 --- a/src/org/torproject/android/Orbot.java +++ b/src/org/torproject/android/Orbot.java @@ -3,6 +3,9 @@ package org.torproject.android; + + + import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -269,255 +272,224 @@ public class Orbot extends Activity implements OnLongClickListener, TorConstants }*/ /* (non-Javadoc) - * @see android.app.Activity#onPause() - */ - protected void onPause() { - super.onPause(); - - hideProgressDialog(); + * @see android.app.Activity#onPause() + */ + protected void onPause() { + super.onPause(); + + hideProgressDialog(); - if (aDialog != null) - aDialog.dismiss(); - } + if (aDialog != null) + aDialog.dismiss(); + } -/** -* i think we need to suport this onSave/Restore code more b/c i think -* when someone rotates the screen, and the state is lost during setup -* etc it causes problems. this might be the place to solve that in the wizard - hmm this prob coz android restarts the activity when the screen is rotated. this will prob be fixed(?) when -we redesign the wizard into a view not just a dialogbox -cool -**/ - public void onSaveInstanceState(Bundle savedInstanceState) { - // Save UI state changes to the savedInstanceState. - // This bundle will be passed to onCreate if the process is - // killed and restarted. - // etc. - super.onSaveInstanceState(savedInstanceState); - } - - public void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - // Restore UI state from the savedInstanceState. - // This bundle has also been passed to onCreate. - - //we do nothing here - } - - /** - * confirm with the user that they want to open a browser to connect to https://check.torproject.org - and then launch the URL. - this may be where the TorCheck API code/UI is added, though always offering the web-based confirm - should be an option, since users know it - - **/ - private void doTorCheck () - { - - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which){ - case DialogInterface.BUTTON_POSITIVE: - - openBrowser(URL_TOR_CHECK); + public void onSaveInstanceState(Bundle savedInstanceState) { + // Save UI state changes to the savedInstanceState. + // This bundle will be passed to onCreate if the process is + // killed and restarted. + // etc. + super.onSaveInstanceState(savedInstanceState); + } + + public void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + // Restore UI state from the savedInstanceState. + // This bundle has also been passed to onCreate. + + } + + private void doTorCheck () + { + + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which){ + case DialogInterface.BUTTON_POSITIVE: + + openBrowser(URL_TOR_CHECK); - - - break; + + + break; - case DialogInterface.BUTTON_NEGATIVE: - - //do nothing - break; - } - } - }; + case DialogInterface.BUTTON_NEGATIVE: + + //do nothing + break; + } + } + }; - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setMessage(R.string.tor_check).setPositiveButton(R.string.btn_okay, dialogClickListener) - .setNegativeButton(R.string.btn_cancel, dialogClickListener).show(); + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage(R.string.tor_check).setPositiveButton(R.string.btn_okay, dialogClickListener) + .setNegativeButton(R.string.btn_cancel, dialogClickListener).show(); - } - - /** - * this adds a port to the list of hidden service ports - * we might want to add remove/disable port too - * this is used by external apps that launch an intent - * to request a hidden service on a specific port - * currently, we haven't promoted this intent API or capability - * that much, but we hope to - **/ - private void enableHiddenServicePort (int hsPort) - { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - Editor pEdit = prefs.edit(); - - String hsPortString = prefs.getString("pref_hs_ports", ""); - - if (hsPortString.length() > 0 && hsPortString.indexOf(hsPort+"")==-1) - hsPortString += ',' + hsPort; - else - hsPortString = hsPort + ""; - - pEdit.putString("pref_hs_ports", hsPortString); - pEdit.putBoolean("pref_hs_enable", true); - - pEdit.commit(); - - String onionHostname = prefs.getString("pref_hs_hostname",""); + } + + private void enableHiddenServicePort (int hsPort) + { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + Editor pEdit = prefs.edit(); + + String hsPortString = prefs.getString("pref_hs_ports", ""); + + if (hsPortString.length() > 0 && hsPortString.indexOf(hsPort+"")==-1) + hsPortString += ',' + hsPort; + else + hsPortString = hsPort + ""; + + pEdit.putString("pref_hs_ports", hsPortString); + pEdit.putBoolean("pref_hs_enable", true); + + pEdit.commit(); + + String onionHostname = prefs.getString("pref_hs_hostname",""); - Intent nResult = new Intent(); - nResult.putExtra("hs_host", onionHostname); - setResult(RESULT_OK, nResult); - - } - - /* (non-Javadoc) - * @see android.app.Activity#onResume() - */ - protected void onResume() { - super.onResume(); - - //this is where we make sure we have a handle to ITorService - bindService(); - - //this is a hack which basically pings the ITorService to update our status for the UI - // - the dialogbox/progressbar ? - // right, this was for when the label displayed the status, and not the progress, so it may - // not make as much sense now; there is a bunch of loose ends like this that should be - // cleaned up with the transition to the progressdialog - ok - updateStatus(""); - - //this checks if we were launched via an Intent call from another app or activity - //- how does this matter? if Orbot has been launched via an Intent or not ? - //we want to know if this is a launch by the user from the home screen, or via back, or some - // standard interaction, or if it is another app launching Orbot for a programmatic/API request - // this is how we can add more functionality into ORlib, for instance via Intent launching - hmm ok - if (getIntent() == null) - return; - - String action = getIntent().getAction(); - - if (action == null) - return; - - //this relates to the previously discussed hidden port capability - if (action.equals("org.torproject.android.REQUEST_HS_PORT")) - { - - //tell the user an app is trying to open a hidden port and ask for permission - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - switch (which){ - case DialogInterface.BUTTON_POSITIVE: - - int hsPort = getIntent().getIntExtra("hs_port", -1); - - enableHiddenServicePort (hsPort); - - finish(); - - - break; + Intent nResult = new Intent(); + nResult.putExtra("hs_host", onionHostname); + setResult(RESULT_OK, nResult); + + } + + /* (non-Javadoc) + * @see android.app.Activity#onResume() + */ + protected void onResume() { + super.onResume(); + + bindService(); + + updateStatus(""); + + if (getIntent() == null) + return; + + String action = getIntent().getAction(); + + if (action == null) + return; + + if (action.equals("org.torproject.android.REQUEST_HS_PORT")) + { + + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which){ + case DialogInterface.BUTTON_POSITIVE: + + int hsPort = getIntent().getIntExtra("hs_port", -1); + + enableHiddenServicePort (hsPort); + + finish(); + + + break; - case DialogInterface.BUTTON_NEGATIVE: - //No button clicked - finish(); - break; - } - } - }; + case DialogInterface.BUTTON_NEGATIVE: + //No button clicked + finish(); + break; + } + } + }; - int hsPort = getIntent().getIntExtra("hs_port", -1); + int hsPort = getIntent().getIntExtra("hs_port", -1); - String requestMsg = "An app wants to open a server port (" + hsPort + ") to the Tor network. This is safe if you trust the app."; - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setMessage(requestMsg).setPositiveButton("Allow", dialogClickListener) - .setNegativeButton("Deny", dialogClickListener).show(); - - - } - else if (action.equals("org.torproject.android.START_TOR")) //this is the intent used to start Tor from another app, again meant for ORlib functionality - { - autoStartOnBind = true; - - if (mService == null) - bindService(); - - } - else - { - //hmm not sure when this is ever reached honestly ;P - //but it looks like a general UI reset - - NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); - mNotificationManager.cancelAll(); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - - boolean showWizard = prefs.getBoolean("show_wizard",true); - - if (showWizard) - { - - Editor pEdit = prefs.edit(); - - pEdit.putBoolean("show_wizard",false); - - pEdit.commit(); - - new WizardHelper(this).showWizard(); + String requestMsg = "An app wants to open a server port (" + hsPort + ") to the Tor network. This is safe if you trust the app."; + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage(requestMsg).setPositiveButton("Allow", dialogClickListener) + .setNegativeButton("Deny", dialogClickListener).show(); + + + } + else if (action.equals("org.torproject.android.START_TOR")) + { + autoStartOnBind = true; + + if (mService == null) + bindService(); + + } + else + { + + //setTitle(getString(R.string.app_name) + ' ' + getString(R.string.app_version)); + + NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + mNotificationManager.cancelAll(); + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + + boolean showWizard = prefs.getBoolean("show_wizard",true); + + if (showWizard) + { + + Editor pEdit = prefs.edit(); + + pEdit.putBoolean("show_wizard",false); + + pEdit.commit(); + + startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1); - } - - } - } + } + + } + } - /* (non-Javadoc) - * @see android.app.Activity#onStart() - */ - protected void onStart() { - super.onStart(); - - - updateStatus (""); - - } + /* (non-Javadoc) + * @see android.app.Activity#onStart() + */ + protected void onStart() { + super.onStart(); + + + updateStatus (""); + + } - /* (non-Javadoc) - * @see android.app.Activity#onStop() - */ - protected void onStop() { - super.onStop(); - - //unbindService(); - } + /* (non-Javadoc) + * @see android.app.Activity#onStop() + */ + protected void onStop() { + super.onStop(); + + //unbindService(); + } - /* - * Launch the system activity for Uri viewing with the provided url - */ - private void openBrowser(String url) - { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - - } - - - - /* - * Show the help view - a popup dialog - */ - private void showHelp () - { - - new WizardHelper(this).showWizard(); - } - - + /* + * Launch the system activity for Uri viewing with the provided url + */ + private void openBrowser(String url) + { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + + + + /* + * Show the help view - a popup dialog + */ + private void showHelp () + { + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + + Editor pEdit = prefs.edit(); + pEdit.putBoolean("wizardscreen1",true); + pEdit.commit(); + startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1); + } + + /* * Load the basic settings application to display torrc */ diff --git a/src/org/torproject/android/Permissions.java b/src/org/torproject/android/Permissions.java new file mode 100644 index 00000000..2ee4f7e3 --- /dev/null +++ b/src/org/torproject/android/Permissions.java @@ -0,0 +1,229 @@ +package org.torproject.android; + +import org.torproject.android.service.TorService; +import org.torproject.android.service.TorServiceUtils; +import org.torproject.android.service.TorTransProxy; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.os.Bundle; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +public class Permissions extends Activity implements TorConstants { + + private Context context; + + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + context = this; + + } + + @Override + protected void onStart() { + + super.onStart(); + setContentView(R.layout.layout_wizard_permissions); + + stepThree(); + + } + + @Override + protected void onResume() { + super.onResume(); + + + } + + private void stepThree(){ + + boolean hasRoot = TorServiceUtils.checkRootAccess(); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + Editor pEdit = prefs.edit(); + pEdit.putBoolean("has_root",hasRoot); + pEdit.commit(); + + if (hasRoot) + { + stepFourRoot(); + } + else + { + stepFour(); + } + + } + + private void stepFourRoot(){ + + String title = context.getString(R.string.wizard_permissions_title); + String msg1 = context.getString(R.string.wizard_permissions_root_msg1); + String msg2 = context.getString(R.string.wizard_permissions_root_msg2); + + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + TextView txtBody1 = ((TextView)findViewById(R.id.WizardTextBody1)); + txtBody1.setText(msg1); + + + TextView txtBody2 = ((TextView)findViewById(R.id.WizardTextBody2)); + txtBody2.setText(msg2); + txtBody2.setVisibility(TextView.VISIBLE); + + Button grantPermissions = ((Button)findViewById(R.id.grantPermissions)); + grantPermissions.setVisibility(Button.VISIBLE); + + Button back = ((Button)findViewById(R.id.btnWizard1)); + Button next = ((Button)findViewById(R.id.btnWizard2)); + next.setEnabled(false); + + CheckBox consent = (CheckBox)findViewById(R.id.checkBox); + consent.setVisibility(CheckBox.VISIBLE); + + consent.setOnCheckedChangeListener(new OnCheckedChangeListener (){ + + @Override + public void onCheckedChanged(CompoundButton buttonView, + boolean isChecked) { + + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + + Editor pEdit = prefs.edit(); + + pEdit.putBoolean(PREF_TRANSPARENT, !isChecked); + pEdit.putBoolean(PREF_TRANSPARENT_ALL, !isChecked); + + pEdit.commit(); + + Button next = ((Button)findViewById(R.id.btnWizard2)); + if(isChecked) + next.setEnabled(true); + else + next.setEnabled(false); + + + } + + }); + + + grantPermissions.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + //Check and Install iptables - TorTransProxy.testOwnerModule(this) + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean hasRoot = prefs.getBoolean("has_root",false); + + if (hasRoot) + { + try { + int resp = TorTransProxy.testOwnerModule(context); + + if (resp < 0) + { + hasRoot = false; + Toast.makeText(context, "ERROR: IPTables OWNER module not available", Toast.LENGTH_LONG).show(); + + Log.i(TorService.TAG,"ERROR: IPTables OWNER module not available"); + stepFour(); + } + + } catch (Exception e) { + + hasRoot = false; + Log.d(TorService.TAG,"ERROR: IPTables OWNER module not available",e); + } + } + + startActivityForResult(new Intent(getBaseContext(), ConfigureTransProxy.class), 1); + + + } + }); + + back.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1); + } + }); + + + next.setOnClickListener(new View.OnClickListener() { + + + @Override + public void onClick(View v) { + startActivityForResult(new Intent(getBaseContext(), TipsAndTricks.class), 1); + } + }); + + } + + private void stepFour(){ + + Toast.makeText(context, "NON ROOT FUNC", Toast.LENGTH_SHORT).show(); + String title = context.getString(R.string.wizard_permissions_title); + String msg = context.getString(R.string.wizard_permissions_msg); + + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + TextView txtBody = ((TextView)findViewById(R.id.WizardTextBody1)); + txtBody.setText(msg); + + Button btn1 = ((Button)findViewById(R.id.btnWizard1)); + Button btn2 = ((Button)findViewById(R.id.btnWizard2)); + btn2.setEnabled(true); + + + TextView txtBody2 = ((TextView)findViewById(R.id.WizardTextBody2)); + txtBody2.setVisibility(TextView.GONE); + + Button grantPermissions = ((Button)findViewById(R.id.grantPermissions)); + grantPermissions.setVisibility(Button.GONE); + + + CheckBox consent = (CheckBox)findViewById(R.id.checkBox); + consent.setVisibility(CheckBox.GONE); + + btn1.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + startActivityForResult(new Intent(getBaseContext(), LotsaText.class), 1); + } + }); + + btn2.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + startActivityForResult(new Intent(getBaseContext(), TipsAndTricks.class), 1); + } + }); + } + + +} \ No newline at end of file diff --git a/src/org/torproject/android/TipsAndTricks.java b/src/org/torproject/android/TipsAndTricks.java new file mode 100644 index 00000000..ebb5ad37 --- /dev/null +++ b/src/org/torproject/android/TipsAndTricks.java @@ -0,0 +1,139 @@ +package org.torproject.android; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; + +public class TipsAndTricks extends Activity implements TorConstants { + + private Context context; + + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + context = this; + + } + + @Override + protected void onStart() { + + super.onStart(); + setContentView(R.layout.layout_wizard_tips); + + stepFive(); + + } + + @Override + protected void onResume() { + super.onResume(); + + + } + + void stepFive(){ + + String title = context.getString(R.string.wizard_tips_title); + TextView txtTitle = ((TextView)findViewById(R.id.WizardTextTitle)); + txtTitle.setText(title); + + Button btn1 = (Button)findViewById(R.id.WizardRootButtonInstallGibberbot); + + btn1.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View view) { + + String url = context.getString(R.string.gibberbot_apk_url); + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + Button btn2 = (Button)findViewById(R.id.WizardRootButtonInstallFirefox); + + btn2.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View view) { + + String url = context.getString(R.string.firefox_apk_url); + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + Button btn3 = (Button)findViewById(R.id.WizardRootButtonInstallProxyMob); + + btn3.setOnClickListener(new OnClickListener() { + + @Override + public void onClick(View view) { + + String url = context.getString(R.string.proxymob_url); + context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + } + }); + + Button back = ((Button)findViewById(R.id.btnWizard1)); + Button next = ((Button)findViewById(R.id.btnWizard2)); + + back.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + + startActivityForResult(new Intent(getBaseContext(), Permissions.class), 1); + } + }); + + next.setOnClickListener(new View.OnClickListener() { + + @Override + public void onClick(View v) { + showWizardFinal(); + } + }); + + } + + private void showWizardFinal () + { + String title = null; + String msg = null; + + + title = context.getString(R.string.wizard_final); + msg = context.getString(R.string.wizard_final_msg); + + DialogInterface.OnClickListener ocListener = new DialogInterface.OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + context.startActivity(new Intent(context, Orbot.class)); + + } + }; + + + new AlertDialog.Builder(context) + .setIcon(R.drawable.icon) + .setTitle(title) + .setPositiveButton(R.string.button_close, ocListener) + .setMessage(msg) + .show(); + + + + + } +} \ No newline at end of file diff --git a/src/org/torproject/android/WizardActivity.java b/src/org/torproject/android/WizardActivity.java deleted file mode 100644 index 2a8bf33e..00000000 --- a/src/org/torproject/android/WizardActivity.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.torproject.android; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; - -public class WizardActivity extends Activity implements OnClickListener -{ - - protected void onCreate(Bundle savedInstanceState) - { - - this.setContentView(R.layout.layout_help); - - } - - - - @Override - protected void onStart() { - - super.onStart(); - - - } - - - - @Override - protected void onResume() { - super.onResume(); - - showStep1(); - } - - - - public void showStep1() - { - showDialog("Test","","foo","bar",this); - } - - private void showDialog (String title, String msg, String button1, String button2, OnClickListener ocListener) - { - - new AlertDialog.Builder(this) - .setInverseBackgroundForced(true) - .setTitle(title) - .setMessage(msg) - .setNeutralButton(button1, ocListener) - .setNegativeButton(button2, ocListener) - .show(); - - - } - - - - @Override - public void onClick(DialogInterface arg0, int arg1) { - - - } - - - -} diff --git a/src/org/torproject/android/WizardHelper.java b/src/org/torproject/android/WizardHelper.java index c3fa3c08..c85c50a0 100644 --- a/src/org/torproject/android/WizardHelper.java +++ b/src/org/torproject/android/WizardHelper.java @@ -215,7 +215,7 @@ public class WizardHelper implements TorConstants { LayoutInflater li = LayoutInflater.from(context); View view = li.inflate(R.layout.layout_wizard_tips, null); - Button btn1 = (Button)view.findViewById(R.id.WizardRootButtonInstallOtrchat); + Button btn1 = (Button)view.findViewById(R.id.WizardRootButtonInstallGibberbot); btn1.setOnClickListener(new OnClickListener() { @@ -228,7 +228,7 @@ public class WizardHelper implements TorConstants { } }); - Button btn2 = (Button)view.findViewById(R.id.WizardRootButtonInstallOrweb); + Button btn2 = (Button)view.findViewById(R.id.WizardRootButtonInstallFirefox); btn2.setOnClickListener(new OnClickListener() { @@ -241,7 +241,7 @@ public class WizardHelper implements TorConstants { } }); - Button btn3 = (Button)view.findViewById(R.id.WizardRootButtonProxyHelp); + Button btn3 = (Button)view.findViewById(R.id.WizardRootButtonInstallProxyMob); btn3.setOnClickListener(new OnClickListener() { @@ -277,7 +277,7 @@ public class WizardHelper implements TorConstants { public void showWizardRootConfigureTorification() { - + /* LayoutInflater li = LayoutInflater.from(context); View view = li.inflate(R.layout.layout_wizard_root, null); @@ -347,7 +347,7 @@ public class WizardHelper implements TorConstants { } }); - + */ } diff --git a/src/org/torproject/android/service/TorServiceUtils.java b/src/org/torproject/android/service/TorServiceUtils.java index 2aa58e67..657d525d 100644 --- a/src/org/torproject/android/service/TorServiceUtils.java +++ b/src/org/torproject/android/service/TorServiceUtils.java @@ -17,7 +17,9 @@ public class TorServiceUtils implements TorServiceConstants { * Check if we have root access * @return boolean true if we have root */ - public static boolean checkRootAccess() { + /* + public static boolean checkRootAccess() { + StringBuilder log = new StringBuilder(); @@ -45,7 +47,40 @@ public class TorServiceUtils implements TorServiceConstants { TorService.logMessage("Could not acquire root permissions"); return false; } + */ + public static boolean checkRootAccess(){ + + StringBuilder log = new StringBuilder(); + + try { + + // Check if Superuser.apk exists + File file = new File("/system/app/Superuser.apk"); + + //Check for 'su' binary + String[] cmd = {"which su"}; + int exitCode = TorServiceUtils.doShellCommand(cmd, log, false, true); + + if (file.exists() && exitCode == 0) { + TorService.logMessage("Can acquire root permissions"); + return true; + + } + + } catch (IOException e) { + //this means that there is no root to be had (normally) so we won't log anything + TorService.logException("Error checking for root access",e); + + } + catch (Exception e) { + TorService.logException("Error checking for root access",e); + //this means that there is no root to be had (normally) + } + + TorService.logMessage("Could not acquire root permissions"); + return false; + } public static int findProcessId(String command)