commit 7c303f1589656c2e6de44b96e710a14aae3ec8f5 Author: Nathan Freitas nathan@freitas.net Date: Mon Feb 2 11:04:32 2015 -0500
refactoring into cleaner packages --- AndroidManifest.xml | 23 +- .../torproject/android/HiddenServiceManager.java | 25 - src/org/torproject/android/ImageProgressView.java | 78 -- src/org/torproject/android/OnBootReceiver.java | 41 - src/org/torproject/android/Orbot.java | 1234 -------------------- .../android/OrbotDiagnosticsActivity.java | 332 ------ src/org/torproject/android/OrbotMainActivity.java | 1196 +++++++++++++++++++ .../torproject/android/RandomColorCircleView.java | 134 --- src/org/torproject/android/Rotate3dAnimation.java | 76 -- src/org/torproject/android/Utils.java | 100 -- src/org/torproject/android/pluto/PlutoFactory.java | 14 + .../torproject/android/pluto/PlutoInstaller.java | 194 +++ .../torproject/android/pluto/PlutoInstance.java | 9 + .../android/service/HiddenServiceManager.java | 25 + .../torproject/android/service/OnBootReceiver.java | 39 + src/org/torproject/android/service/TorService.java | 5 +- src/org/torproject/android/service/Utils.java | 100 ++ .../android/ui/ChooseLocaleWizardActivity.java | 136 +++ .../torproject/android/ui/ImageProgressView.java | 78 ++ src/org/torproject/android/ui/LotsaText.java | 137 +++ .../android/ui/OrbotDiagnosticsActivity.java | 337 ++++++ .../torproject/android/ui/OrbotLogActivity.java | 75 ++ .../torproject/android/ui/Rotate3dAnimation.java | 76 ++ src/org/torproject/android/ui/TipsAndTricks.java | 248 ++++ .../torproject/android/vpn/OrbotVpnService.java | 19 +- .../android/wizard/ChooseLocaleWizardActivity.java | 136 --- src/org/torproject/android/wizard/LotsaText.java | 137 --- .../torproject/android/wizard/TipsAndTricks.java | 248 ---- 28 files changed, 2695 insertions(+), 2557 deletions(-)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 416c9b6..6681cd4 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.torproject.android" - android:versionName="15.1.0" - android:versionCode="1510" + android:versionName="15.0.0-alpha-1" + android:versionCode="15001" android:installLocation="auto" > @@ -29,7 +29,7 @@ android:largeHeap="false" >
- <activity android:name=".Orbot" + <activity android:name=".OrbotMainActivity" android:configChanges="orientation|screenSize" android:excludeFromRecents="true" android:launchMode="singleTop" @@ -63,6 +63,12 @@
</activity>
+ + <activity android:name=".ui.OrbotLogActivity" + android:configChanges="orientation|screenSize" + android:exported="false" + /> + <!-- This is for ensuring the background service still runs when/if the app is swiped away --> @@ -77,14 +83,13 @@ android:stateNotNeeded="true" android:clearTaskOnLaunch="true" android:finishOnTaskLaunch="true" + /> - <activity android:name=".wizard.LotsaText" android:exported="false"/> - <activity android:name=".wizard.Permissions" android:exported="false"/> - <activity android:name=".wizard.TipsAndTricks" android:exported="false"/> - <activity android:name=".wizard.ConfigureTransProxy" android:exported="false"/> - <activity android:name=".wizard.ChooseLocaleWizardActivity" android:exported="false"/> + <activity android:name=".ui.LotsaText" android:exported="false"/> + <activity android:name=".ui.TipsAndTricks" android:exported="false"/> + <activity android:name=".ui.ChooseLocaleWizardActivitycaleWizardActivity" android:exported="false"/> <activity android:name=".settings.SettingsPreferences" android:label="@string/app_name"/> <activity android:name=".settings.AppManager" android:label="@string/app_name"/> @@ -143,7 +148,7 @@ </intent-filter> </service> - <receiver android:name=".OnBootReceiver"> + <receiver android:name="org.torproject.android.service.OnBootReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" /> diff --git a/src/org/torproject/android/HiddenServiceManager.java b/src/org/torproject/android/HiddenServiceManager.java deleted file mode 100644 index ca8f7e5..0000000 --- a/src/org/torproject/android/HiddenServiceManager.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.torproject.android; - - -//list view with add/remove hidden services - user is prompted for port - -public class HiddenServiceManager { - -} -/* - * - * ## Once you have configured a hidden service, you can look at the -## contents of the file ".../hidden_service/hostname" for the address -## to tell people. -## -## HiddenServicePort x y:z says to redirect requests on port x to the -## address y:z. - -#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/ -#HiddenServicePort 80 127.0.0.1:80 - -#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/other_hidden_service/ -#HiddenServicePort 80 127.0.0.1:80 -#HiddenServicePort 22 127.0.0.1:22 -*/ - diff --git a/src/org/torproject/android/ImageProgressView.java b/src/org/torproject/android/ImageProgressView.java deleted file mode 100644 index 6e813eb..0000000 --- a/src/org/torproject/android/ImageProgressView.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.torproject.android; - -import java.util.Random; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; -import android.widget.ImageView; - -public class ImageProgressView extends ImageView -{ - - private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - - private float progress = 0f; // 0 to 1 - - private RectF circle; - - public ImageProgressView(Context context) { - super(context); - // TODO Auto-generated constructor stub - init(); - - } - - public ImageProgressView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public ImageProgressView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - init(); - } - - private void init(){ - paint.setStyle(Paint.Style.STROKE); - paint.setColor(Color.GREEN); - paint.setAntiAlias(true); - paint.setStrokeWidth(20); - - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), - MeasureSpec.getSize(heightMeasureSpec)); - - } - - @Override - protected void onDraw(Canvas canvas) { - - super.onDraw(canvas); - - if (circle == null) - { - circle = new RectF(getWidth()/2,getHeight()/2+getHeight()/8, getWidth()/3,getHeight()/3); - } - - float sweepAngle = 360f * progress; - - canvas.drawArc(circle, 0, sweepAngle, true, paint); - - } - - - - -} \ No newline at end of file diff --git a/src/org/torproject/android/OnBootReceiver.java b/src/org/torproject/android/OnBootReceiver.java deleted file mode 100644 index 0e34f50..0000000 --- a/src/org/torproject/android/OnBootReceiver.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.torproject.android; - -import org.torproject.android.service.TorService; -import org.torproject.android.service.TorServiceUtils; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; - -public class OnBootReceiver extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(context.getApplicationContext()); - - boolean startOnBoot = prefs.getBoolean("pref_start_boot",true); - - if (startOnBoot) - { - startService("init",context); - startService("start",context); - } - - } - - - private void startService (String action, Context context) - { - - Intent torService = new Intent(context, TorService.class); - torService.setAction(action); - context.startService(torService); - - - } - - -} - diff --git a/src/org/torproject/android/Orbot.java b/src/org/torproject/android/Orbot.java deleted file mode 100644 index edb3c09..0000000 --- a/src/org/torproject/android/Orbot.java +++ /dev/null @@ -1,1234 +0,0 @@ -/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - https://guardianproject.info */ -/* See LICENSE for licensing information */ - -package org.torproject.android; - -import static org.torproject.android.TorConstants.TAG; -import info.guardianproject.browser.Browser; - -import java.net.URLDecoder; -import java.util.Locale; - -import org.torproject.android.service.TorService; -import org.torproject.android.service.TorServiceConstants; -import org.torproject.android.service.TorServiceUtils; -import org.torproject.android.settings.SettingsPreferences; -import org.torproject.android.wizard.ChooseLocaleWizardActivity; - -import android.annotation.TargetApi; -import android.app.AlertDialog; -import android.app.ProgressDialog; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Configuration; -import android.net.Uri; -import android.net.VpnService; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.RemoteException; -import android.support.v4.content.LocalBroadcastManager; -import android.support.v7.app.ActionBarActivity; -import android.util.Log; -import android.view.GestureDetector; -import android.view.GestureDetector.SimpleOnGestureListener; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnLongClickListener; -import android.view.View.OnTouchListener; -import android.view.animation.AccelerateInterpolator; -import android.widget.Button; -import android.widget.TextView; -import android.widget.Toast; - - -public class Orbot extends ActionBarActivity implements TorConstants, OnLongClickListener, OnTouchListener, OnSharedPreferenceChangeListener -{ - /* Useful UI bits */ - //private TextView lblStatus = null; //the main text display widget - private ImageProgressView imgStatus = null; //the main touchable image for activating Orbot - - private MenuItem mItemOnOff = null; - private TextView downloadText = null; - private TextView uploadText = null; - private boolean mDrawerOpen = false; - - private Button mBtnBrowser = null; - private Button mBtnVPN = null; - - /* Some tracking bits */ - private int torStatus = TorServiceConstants.STATUS_OFF; //latest status reported from the tor service - - private SharedPreferences mPrefs = null; - - private boolean autoStartFromIntent = false; - - private final static long INIT_DELAY = 100; - - /** Called when the activity is first created. */ - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mPrefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - mPrefs.registerOnSharedPreferenceChangeListener(this); - - setLocale(); - - doLayout(); - - // appConflictChecker (); - - - // Register to receive messages. - // We are registering an observer (mMessageReceiver) to receive Intents - // with actions named "custom-event-name". - LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, - new IntentFilter("status")); - - LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, - new IntentFilter("log")); - - mHandler.postDelayed(new Runnable () - { - - public void run () - { - startService(TorServiceConstants.CMD_INIT); - } - },INIT_DELAY); - - } - - // Our handler for received Intents. This will be called whenever an Intent - // with an action named "custom-event-name" is broadcasted. - private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { - - - - @Override - public void onReceive(Context context, Intent intent) { - // Get extra data included in the Intent - - if (intent.hasExtra("log")) - { - String log = intent.getStringExtra("log"); - updateStatus(log); - } - else if (intent.hasExtra("up")) - { - long upload = intent.getLongExtra("up",0); - long download = intent.getLongExtra("down",0); - long written = intent.getLongExtra("written",0); - long read = intent.getLongExtra("read",0); - - Message msg = mHandler.obtainMessage(TorServiceConstants.MESSAGE_TRAFFIC_COUNT); - msg.getData().putLong("download", download); - msg.getData().putLong("upload", upload); - msg.getData().putLong("readTotal", read); - msg.getData().putLong("writeTotal", written); - mHandler.sendMessage(msg); - - } - else if (intent.hasExtra("status")) - { - torStatus = intent.getIntExtra("status", TorServiceConstants.STATUS_OFF); - updateStatus(""); - } - - } - }; - - ProgressDialog mProgressDialog; - - private void startService (String action) - { - - Intent torService = new Intent(this, TorService.class); - torService.setAction(action); - startService(torService); - - } - - private void stopService () - { - - Intent torService = new Intent(this, TorService.class); - stopService(torService); - - } - - private void doLayout () - { - setContentView(R.layout.layout_main); - - // lblStatus = (TextView)findViewById(R.id.lblStatus); -// lblStatus.setOnLongClickListener(this); - imgStatus = (ImageProgressView)findViewById(R.id.imgStatus); - imgStatus.setOnLongClickListener(this); - imgStatus.setOnTouchListener(this); - - // lblStatus.setText("Initializing the application..."); - - downloadText = (TextView)findViewById(R.id.trafficDown); - uploadText = (TextView)findViewById(R.id.trafficUp); - // mTxtOrbotLog = (TextView)findViewById(R.id.orbotLog); - - /* - mDrawer = ((SlidingDrawer)findViewById(R.id.SlidingDrawer)); - Button slideButton = (Button)findViewById(R.id.slideButton); - if (slideButton != null) - { - slideButton.setOnTouchListener(new OnTouchListener (){ - - @Override - public boolean onTouch(View v, MotionEvent event) { - - if (event.equals(MotionEvent.ACTION_DOWN)) - { - mDrawerOpen = !mDrawerOpen; - mTxtOrbotLog.setEnabled(mDrawerOpen); - } - return false; - } - - }); - }*/ - - /* - ScrollingMovementMethod smm = new ScrollingMovementMethod(); - - mTxtOrbotLog.setMovementMethod(smm); - mTxtOrbotLog.setOnLongClickListener(new View.OnLongClickListener() { - - - @Override - public boolean onLongClick(View v) { - ClipboardManager cm = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE); - cm.setText(mTxtOrbotLog.getText()); - Toast.makeText(Orbot.this, "LOG COPIED TO CLIPBOARD", Toast.LENGTH_SHORT).show(); - return true; - } - });*/ - - downloadText.setText(formatCount(0) + " / " + formatTotal(0)); - uploadText.setText(formatCount(0) + " / " + formatTotal(0)); - - // Gesture detection - mGestureDetector = new GestureDetector(this, new MyGestureDetector()); - - mBtnBrowser = (Button)findViewById(R.id.btnBrowser); - mBtnBrowser.setOnClickListener(new View.OnClickListener () - { - - @Override - public void onClick(View v) { - doTorCheck(); - - } - - - }); - - mBtnVPN = (Button)findViewById(R.id.btnVPN); - mBtnVPN.setOnClickListener(new View.OnClickListener () - { - - @Override - public void onClick(View v) { - - startVpnService(); - - } - - - }); - - - } - - GestureDetector mGestureDetector; - - - @Override - public boolean onTouch(View v, MotionEvent event) { - return mGestureDetector.onTouchEvent(event); - - } - - /* - private void appendLogTextAndScroll(String text) - { - - if(mTxtOrbotLog != null && text != null && text.length() > 0){ - - if (mTxtOrbotLog.getText().length() > MAX_LOG_LENGTH) - mTxtOrbotLog.setText(""); - - mTxtOrbotLog.append(text + "\n"); - final Layout layout = mTxtOrbotLog.getLayout(); - if(layout != null){ - int scrollDelta = layout.getLineBottom(mTxtOrbotLog.getLineCount() - 1) - - mTxtOrbotLog.getScrollY() - mTxtOrbotLog.getHeight(); - if(scrollDelta > 0) - mTxtOrbotLog.scrollBy(0, scrollDelta); - } - } - }*/ - - /* - * Create the UI Options Menu (non-Javadoc) - * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu) - */ - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.orbot_main, menu); - - mItemOnOff = menu.getItem(0); - - return true; - } - - /** - private void appConflictChecker () - { - SharedPreferences sprefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - boolean showAppConflict = true;//sprefs.getBoolean("pref_show_conflict",true); - - String[] badApps = {"com.sec.msc.nts.android.proxy:com.sec.msc.nts.android.proxy","com.sec.pcw:Samsung Link"}; - - for (String badApp : badApps) - { - String[] badAppParts = badApp.split(":"); - - if (appInstalledOrNot(badAppParts[0])) - { - String msg = getString(R.string.please_disable_this_app_in_android_settings_apps_if_you_are_having_problems_with_orbot_) + badAppParts[1]; - - if (showAppConflict) - showAlert(getString(R.string.app_conflict),msg,true); - - // appendLogTextAndScroll(msg); - } - } - - sprefs.edit().putBoolean("pref_show_conflict", false).commit(); - - }*/ - - - - - private void showAbout () - { - - LayoutInflater li = LayoutInflater.from(this); - View view = li.inflate(R.layout.layout_about, null); - - String version = ""; - - try { - version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName + " (Tor " + TorServiceConstants.BINARY_TOR_VERSION + ")"; - } catch (NameNotFoundException e) { - version = "Version Not Found"; - } - - TextView versionName = (TextView)view.findViewById(R.id.versionName); - versionName.setText(version); - - new AlertDialog.Builder(this) - .setTitle(getString(R.string.button_about)) - .setView(view) - .show(); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - super.onOptionsItemSelected(item); - - if (item.getItemId() == R.id.menu_start) - { - - try - { - - if (torStatus == TorServiceConstants.STATUS_OFF) - { - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_stop); - startTor(); - - } - else - { - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_start); - - stopTor(); - stopService (); - - } - - } - catch (RemoteException re) - { - Log.w(TAG, "Unable to start/top Tor from menu UI", re); - } - } - else if (item.getItemId() == R.id.menu_settings) - { - showSettings(); - } - else if (item.getItemId() == R.id.menu_wizard) - { - startActivity(new Intent(this, ChooseLocaleWizardActivity.class)); - - } - else if (item.getItemId() == R.id.menu_exit) - { - //exit app - doExit(); - - - } - else if (item.getItemId() == R.id.menu_about) - { - showAbout(); - - - } - - /** - else if (item.getItemId() == R.id.menu_verify) - { - doTorCheck(); - } - else if (item.getItemId() == R.id.menu_vpn) - { - startVpnService(); - }*/ - - return true; - } - - /** - * This is our attempt to REALLY exit Orbot, and stop the background service - * However, Android doesn't like people "quitting" apps, and/or our code may not - * be quite right b/c no matter what we do, it seems like the TorService still exists - **/ - private void doExit () - { - try { - - //one of the confusing things about all of this code is the multiple - //places where things like "stopTor" are called, both in the Activity and the Service - //not something to tackle in your first iteration, but i thin we can talk about fixing - //terminology but also making sure there are clear distinctions in control - stopTor(); - stopService (); - - - } catch (RemoteException e) { - Log.w(TAG, e); - } - - //Kill all the wizard activities - setResult(RESULT_CLOSE_ALL); - finish(); - - } - - /* (non-Javadoc) - * @see android.app.Activity#onPause() - */ - protected void onPause() { - try - { - super.onPause(); - - if (aDialog != null) - aDialog.dismiss(); - } - catch (IllegalStateException ise) - { - //can happen on exit/shutdown - } - } - - private void doTorCheck () - { - - openBrowser(URL_TOR_CHECK); - - - } - - private void enableHiddenServicePort (int hsPort) - { - - Editor pEdit = mPrefs.edit(); - - String hsPortString = mPrefs.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 = mPrefs.getString("pref_hs_hostname",""); - - while (onionHostname.length() == 0) - { - //we need to stop and start Tor - try { - stopTor(); - - Thread.sleep(3000); //wait three seconds - - startTor(); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - onionHostname = mPrefs.getString("pref_hs_hostname",""); - } - - Intent nResult = new Intent(); - nResult.putExtra("hs_host", onionHostname); - setResult(RESULT_OK, nResult); - - } - - - private synchronized void handleIntents () - { - if (getIntent() == null) - return; - - // Get intent, action and MIME type - Intent intent = getIntent(); - String action = intent.getAction(); - String type = intent.getType(); - - if (action == null) - return; - - if (action.equals("org.torproject.android.REQUEST_HS_PORT")) - { - - DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { - - 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; - } - } - }; - - int hsPort = getIntent().getIntExtra("hs_port", -1); - - String requestMsg = getString(R.string.hidden_service_request, hsPort); - 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")) - { - autoStartFromIntent = true; - - try { - startTor(); - - Intent nResult = new Intent(); - - //nResult.putExtra("socks", ); //TODO respond with socks, transport, dns, etc - - setResult(RESULT_OK,nResult); - - } catch (RemoteException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - } - else if (action.equals(Intent.ACTION_VIEW)) - { - String urlString = intent.getDataString(); - - if (urlString != null) - { - - if (urlString.toLowerCase().startsWith("bridge://")) - - { - String newBridgeValue = urlString.substring(9); //remove the bridge protocol piece - newBridgeValue = URLDecoder.decode(newBridgeValue); //decode the value here - - showAlert("Bridges Updated","Restart Orbot to use this bridge: " + newBridgeValue,false); - - String bridges = mPrefs.getString(TorConstants.PREF_BRIDGES_LIST, null); - - Editor pEdit = mPrefs.edit(); - - if (bridges != null && bridges.trim().length() > 0) - { - if (bridges.indexOf('\n')!=-1) - bridges += '\n' + newBridgeValue; - else - bridges += ',' + newBridgeValue; - } - else - bridges = newBridgeValue; - - pEdit.putString(TorConstants.PREF_BRIDGES_LIST,bridges); //set the string to a preference - pEdit.putBoolean(TorConstants.PREF_BRIDGES_ENABLED,true); - - pEdit.commit(); - - setResult(RESULT_OK); - } - } - } - else - { - - showWizard = mPrefs.getBoolean("show_wizard",showWizard); - - if (showWizard) - { - Editor pEdit = mPrefs.edit(); - pEdit.putBoolean("show_wizard",false); - pEdit.commit(); - showWizard = false; - - startActivity(new Intent(this, ChooseLocaleWizardActivity.class)); - - } - - } - - setIntent(null); - - updateStatus (""); - - } - - private boolean showWizard = true; - - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - doLayout(); - updateStatus(""); - } - - - /* - * Launch the system activity for Uri viewing with the provided url - */ - private void openBrowser(final String browserLaunchUrl) - { - //startIntent("info.guardianproject.browser.Browser",Intent.ACTION_VIEW,Uri.parse(browserLaunchUrl)); - - Intent intentBrowser = new Intent(this, Browser.class); - intentBrowser.setAction(Intent.ACTION_VIEW); - intentBrowser.setData(Uri.parse(browserLaunchUrl)); - startActivity(intentBrowser); - - /** - boolean isOrwebInstalled = appInstalledOrNot("info.guardianproject.browser"); - boolean isTransProxy = mPrefs.getBoolean("pref_transparent", false); - - if (isOrwebInstalled) - { - } - else if (isTransProxy) - { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(browserLaunchUrl)); - intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - } - else - { - AlertDialog aDialog = new AlertDialog.Builder(Orbot.this) - .setIcon(R.drawable.onion32) - .setTitle(R.string.install_apps_) - .setMessage(R.string.it_doesn_t_seem_like_you_have_orweb_installed_want_help_with_that_or_should_we_just_open_the_browser_) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener () - { - - @Override - public void onClick(DialogInterface dialog, int which) { - - //prompt to install Orweb - Intent intent = new Intent(Orbot.this,TipsAndTricks.class); - startActivity(intent); - - } - - }) - .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener () - { - - @Override - public void onClick(DialogInterface dialog, int which) { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(browserLaunchUrl)); - intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - - } - - }) - .show(); - - }*/ - - } - - private void startIntent (String pkg, String action, Uri data) - { - Intent i; - PackageManager manager = getPackageManager(); - try { - i = manager.getLaunchIntentForPackage(pkg); - if (i == null) - throw new PackageManager.NameNotFoundException(); - i.setAction(action); - i.setData(data); - startActivity(i); - } catch (PackageManager.NameNotFoundException e) { - - } - } - - private boolean appInstalledOrNot(String uri) - { - PackageManager pm = getPackageManager(); - try - { - PackageInfo pi = pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES); - return pi.applicationInfo.enabled; - } - catch (PackageManager.NameNotFoundException e) - { - return false; - } -} - - /* - * Load the basic settings application to display torrc - */ - private void showSettings () - { - - startActivityForResult(new Intent(this, SettingsPreferences.class), 1); - } - - - @Override - protected void onActivityResult(int request, int response, Intent data) { - super.onActivityResult(request, response, data); - - - if (request == 1 && response == RESULT_OK) - { - if (data != null && data.getBooleanExtra("transproxywipe", false)) - { - - boolean result = flushTransProxy(); - - if (result) - { - - Toast.makeText(this, R.string.transparent_proxy_rules_flushed_, Toast.LENGTH_SHORT).show(); - - } - else - { - - Toast.makeText(this, R.string.you_do_not_have_root_access_enabled, Toast.LENGTH_SHORT).show(); - - } - - } - else if (torStatus == TorServiceConstants.STATUS_ON) - { - updateSettings(); - Toast.makeText(this, R.string.you_may_need_to_stop_and_start_orbot_for_settings_change_to_be_enabled_, Toast.LENGTH_SHORT).show(); - - } - } - else if (request == REQUEST_VPN && response == RESULT_OK) - { - startService(TorServiceConstants.CMD_VPN); - } - - } - - private final static int REQUEST_VPN = 8888; - - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) - public void startVpnService () - { - Intent intent = VpnService.prepare(this); - if (intent != null) { - startActivityForResult(intent,REQUEST_VPN); - } - else - { - startService(TorServiceConstants.CMD_VPN); - - } - } - - private boolean flushTransProxy () - { - startService(TorServiceConstants.CMD_FLUSH); - return true; - } - - private boolean updateSettings () - { - //todo send service command - startService(TorServiceConstants.CMD_UPDATE); - return true; - } - - @Override - protected void onResume() { - super.onResume(); - - mHandler.postDelayed(new Runnable () - { - public void run () - { - - setLocale(); - - handleIntents(); - - } - } - , 500); - - - } - - AlertDialog aDialog = null; - - //general alert dialog for mostly Tor warning messages - //sometimes this can go haywire or crazy with too many error - //messages from Tor, and the user cannot stop or exit Orbot - //so need to ensure repeated error messages are not spamming this method - private void showAlert(String title, String msg, boolean button) - { - try - { - if (aDialog != null && aDialog.isShowing()) - aDialog.dismiss(); - } - catch (Exception e){} //swallow any errors - - if (button) - { - aDialog = new AlertDialog.Builder(Orbot.this) - .setIcon(R.drawable.onion32) - .setTitle(title) - .setMessage(msg) - .setPositiveButton(android.R.string.ok, null) - .show(); - } - else - { - aDialog = new AlertDialog.Builder(Orbot.this) - .setIcon(R.drawable.onion32) - .setTitle(title) - .setMessage(msg) - .show(); - } - - aDialog.setCanceledOnTouchOutside(true); - } - - private void updateStatus (String torServiceMsg) - { - - //now update the layout_main UI based on the status - if (imgStatus != null) - { - - if (torStatus == TorServiceConstants.STATUS_ON) - { - - imgStatus.setImageResource(R.drawable.toron); - - mBtnBrowser.setEnabled(true); - mBtnVPN.setEnabled(true); - - String lblMsg = getString(R.string.status_activated); - //lblStatus.setText(lblMsg); - - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_stop); - - - if (torServiceMsg != null && torServiceMsg.length() > 0) - { - // appendLogTextAndScroll(torServiceMsg); - } - - boolean showFirstTime = mPrefs.getBoolean("connect_first_time",true); - - if (showFirstTime) - { - - Editor pEdit = mPrefs.edit(); - - pEdit.putBoolean("connect_first_time",false); - - pEdit.commit(); - - showAlert(getString(R.string.status_activated),getString(R.string.connect_first_time),true); - - } - - - if (autoStartFromIntent) - { - setResult(RESULT_OK); - finish(); - } - - } - else if (torStatus == TorServiceConstants.STATUS_CONNECTING) - { - - imgStatus.setImageResource(R.drawable.torstarting); - - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_stop); - - /** - if (lblStatus != null && torServiceMsg != null) - if (torServiceMsg.indexOf('%')!=-1) - lblStatus.setText(torServiceMsg); - **/ - - //appendLogTextAndScroll(torServiceMsg); - - - } - else if (torStatus == TorServiceConstants.STATUS_OFF) - { - imgStatus.setImageResource(R.drawable.toroff); - //lblStatus.setText(getString(R.string.status_disabled) + "\n" + getString(R.string.press_to_start)); - - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_start); - - mBtnBrowser.setEnabled(false); - mBtnVPN.setEnabled(false); - - } - } - - - } - - - - // guess what? this start's Tor! actually no it just requests via the local ITorService to the remote TorService instance - // to start Tor - private void startTor () throws RemoteException - { - - - startService (TorServiceConstants.CMD_START); - torStatus = TorServiceConstants.STATUS_CONNECTING; - -// mTxtOrbotLog.setText(""); - - //here we update the UI which is a bit sloppy and mixed up code wise - //might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense - imgStatus.setImageResource(R.drawable.torstarting); - // lblStatus.setText(getString(R.string.status_starting_up)); - - //we send a message here to the progressDialog i believe, but we can clarify that shortly - Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); - msg.getData().putString(HANDLER_TOR_MSG, getString(R.string.status_starting_up)); - mHandler.sendMessage(msg); - - - - } - - //now we stop Tor! amazing! - private void stopTor () throws RemoteException - { - - startService (TorServiceConstants.CMD_STOP); - torStatus = TorServiceConstants.STATUS_OFF; - - Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG); - mHandler.sendMessage(msg); - - - - } - - /* - * (non-Javadoc) - * @see android.view.View.OnClickListener#onClick(android.view.View) - */ - public boolean onLongClick(View view) { - - if (!mDrawerOpen) - { - try - { - - if (torStatus == TorServiceConstants.STATUS_OFF) - { - - startTor(); - } - else - { - - stopTor(); - stopService (); - - } - - return true; - - } - catch (Exception e) - { - Log.d(TAG,"error onclick",e); - } - - } - - return false; - - } - - - - - -// this is what takes messages or values from the callback threads or other non-mainUI threads -//and passes them back into the main UI thread for display to the user - private Handler mHandler = new Handler() { - - private String lastServiceMsg = null; - - public void handleMessage(Message msg) { - switch (msg.what) { - case TorServiceConstants.STATUS_MSG: - case TorServiceConstants.LOG_MSG: - - String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG); - - if (lastServiceMsg == null || !lastServiceMsg.equals(torServiceMsg)) - { - updateStatus(torServiceMsg); - - lastServiceMsg = torServiceMsg; - } - - break; - case TorServiceConstants.ENABLE_TOR_MSG: - - - updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); - - break; - case TorServiceConstants.DISABLE_TOR_MSG: - - updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); - - break; - - - case TorServiceConstants.MESSAGE_TRAFFIC_COUNT : - - Bundle data = msg.getData(); - DataCount datacount = new DataCount(data.getLong("upload"),data.getLong("download")); - - long totalRead = data.getLong("readTotal"); - long totalWrite = data.getLong("writeTotal"); - - downloadText.setText(formatCount(datacount.Download) + " / " + formatTotal(totalRead)); - uploadText.setText(formatCount(datacount.Upload) + " / " + formatTotal(totalWrite)); - - if (torStatus != TorServiceConstants.STATUS_ON) - { - updateStatus(""); - } - - default: - super.handleMessage(msg); - } - } - - - - }; - - - /** - * Class for interacting with the main interface of the service. - */ - // this is the connection that gets called back when a successfull bind occurs - // we should use this to activity monitor unbind so that we don't have to call - // bindService() a million times - - private void setLocale () - { - - - Configuration config = getResources().getConfiguration(); - String lang = mPrefs.getString(PREF_DEFAULT_LOCALE, ""); - - if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang)) - { - Locale locale = new Locale(lang); - Locale.setDefault(locale); - config.locale = locale; - getResources().updateConfiguration(config, getResources().getDisplayMetrics()); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); - - } - - public class DataCount { - // data uploaded - public long Upload; - // data downloaded - public long Download; - - DataCount(long Upload, long Download){ - this.Upload = Upload; - this.Download = Download; - } - } - - private String formatCount(long count) { - // Converts the supplied argument into a string. - // Under 2Mb, returns "xxx.xKb" - // Over 2Mb, returns "xxx.xxMb" - if (count < 1e6) - return ((float)((int)(count*10/1024))/10 + "kbps"); - return ((float)((int)(count*100/1024/1024))/100 + "mbps"); - - //return count+" kB"; - } - - private String formatTotal(long count) { - // Converts the supplied argument into a string. - // Under 2Mb, returns "xxx.xKb" - // Over 2Mb, returns "xxx.xxMb" - if (count < 1e6) - return ((float)((int)(count*10/1024))/10 + "KB"); - return ((float)((int)(count*100/1024/1024))/100 + "MB"); - - //return count+" kB"; - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - - - } - - private static final float ROTATE_FROM = 0.0f; - private static final float ROTATE_TO = 360.0f*4f;// 3.141592654f * 32.0f; - - public void spinOrbot (float direction) - { - startService (TorServiceConstants.CMD_NEWNYM); - - - Toast.makeText(this, R.string.newnym, Toast.LENGTH_SHORT).show(); - - // Rotate3dAnimation rotation = new Rotate3dAnimation(ROTATE_FROM, ROTATE_TO*direction, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); - Rotate3dAnimation rotation = new Rotate3dAnimation(ROTATE_FROM, ROTATE_TO*direction, imgStatus.getWidth()/2f,imgStatus.getWidth()/2f,20f,false); - rotation.setFillAfter(true); - rotation.setInterpolator(new AccelerateInterpolator()); - rotation.setDuration((long) 2*1000); - rotation.setRepeatCount(0); - imgStatus.startAnimation(rotation); - - - } - - class MyGestureDetector extends SimpleOnGestureListener { - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - try { - if (torStatus == TorServiceConstants.STATUS_ON) - { - float direction = 1f; - if (velocityX < 0) - direction = -1f; - spinOrbot (direction); - } - } catch (Exception e) { - // nothing - } - return false; - } - - } - - -} diff --git a/src/org/torproject/android/OrbotDiagnosticsActivity.java b/src/org/torproject/android/OrbotDiagnosticsActivity.java deleted file mode 100644 index b639d82..0000000 --- a/src/org/torproject/android/OrbotDiagnosticsActivity.java +++ /dev/null @@ -1,332 +0,0 @@ -package org.torproject.android; - -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.ArrayList; - -import org.sufficientlysecure.rootcommands.Shell; -import org.sufficientlysecure.rootcommands.command.SimpleCommand; -import org.torproject.android.service.TorResourceInstaller; -import org.torproject.android.service.TorServiceConstants; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.Environment; -import android.os.Handler; -import android.os.Message; -import android.os.StatFs; -import android.text.format.Formatter; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.TextView; - - -public class OrbotDiagnosticsActivity extends Activity { - - private TextView mTextView = null; - private final static String TAG = "OrbotDiag"; - private StringBuffer log = new StringBuffer(); - Process mProcess; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.layout_diag); - - mTextView = (TextView)findViewById(R.id.diaglog); - - } - - private String getFreeStorage () - { - File path = Environment.getDataDirectory(); - StatFs stat = new StatFs(path.getPath()); - long blockSize = stat.getBlockSize(); - long availableBlocks = stat.getAvailableBlocks(); - return Formatter.formatFileSize(this, availableBlocks * blockSize); - } - - @Override - protected void onPause() { - super.onPause(); - - stopTor(); - } - - @Override - protected void onDestroy() { - - super.onDestroy(); - - } - - private void stopTor () - { - File appBinHome = this.getDir("bin", Context.MODE_PRIVATE); - - File fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY); - - if (mProcess != null) - mProcess.destroy(); - - - } - - - - @Override - protected void onResume() { - super.onResume(); - - - log("Hello, Orbot!"); - - try - { - log(android.os.Build.DEVICE); - log(android.os.Build.HARDWARE); - log(android.os.Build.MANUFACTURER); - log(android.os.Build.MODEL); - log(android.os.Build.VERSION.CODENAME); - log(android.os.Build.VERSION.RELEASE); - } - catch (Exception e) - { - log("error getting device info"); - } - - showFileTree (); - - runTorTest(); - } - - private void runTorTest () - { - try - { - File appBinHome = this.getDir("bin", Context.MODE_PRIVATE); - File appDataHome = this.getDir("data", Context.MODE_PRIVATE); - - File fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY); - enableBinExec (fileTor, appBinHome); - - InputStream is = getResources().openRawResource(R.raw.torrc); - File fileTorrc = new File(appBinHome, TorServiceConstants.TORRC_ASSET_KEY + "diag"); - TorResourceInstaller.streamToFile(is,fileTorrc, false, false); - - /** - ArrayList<String> alEnv = new ArrayList<String>(); - alEnv.add("HOME=" + appBinHome.getAbsolutePath()); - Shell shell = Shell.startShell(alEnv,appBinHome.getAbsolutePath()); - SimpleCommand cmdTor = new SimpleCommand(fileTor.getAbsolutePath() + " DataDirectory " + appDataHome.getAbsolutePath() + " -f " + fileTorrc.getAbsolutePath()); - shell.add(cmdTor); - **/ - - String cmd = fileTor.getAbsolutePath() + " DataDirectory " + appDataHome.getAbsolutePath() + " -f " + fileTorrc.getAbsolutePath(); - - log ("Executing command> " + cmd); - - mProcess = Runtime.getRuntime().exec(cmd); - - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream())); - StreamGobbler sg = new StreamGobbler(); - sg.reader = bufferedReader; - sg.process = mProcess; - new Thread(sg).start(); - - if (mProcess.getErrorStream() != null) - { - bufferedReader = new BufferedReader(new InputStreamReader(mProcess.getErrorStream())); - sg = new StreamGobbler(); - sg.reader = bufferedReader; - sg.process = mProcess; - new Thread(sg).start(); - } - - - } - catch (Exception e) - { - Log.d(TAG,"runTorTest exception",e); - } - - } - - class StreamGobbler implements Runnable - { - BufferedReader reader; - Process process; - - public void run () - { - String line = null; - try { - while ( (line = reader.readLine()) != null) - { - Message msg = mHandler.obtainMessage(0); - msg.getData().putString("log", line); - mHandler.sendMessage(msg); - } - - } catch (IOException e) { - Log.d(TAG, "error reading line",e); - } - - //log("Tor exit code=" + process.exitValue() + ";"); - - } - } - - private boolean enableBinExec (File fileBin, File appBinHome) throws Exception - { - - log(fileBin.getName() + ": PRE: Is binary exec? " + fileBin.canExecute()); - - if (!fileBin.canExecute()) - { - log("(re)Setting permission on binary: " + fileBin.getAbsolutePath()); - Shell shell = Shell.startShell(new ArrayList<String>(), appBinHome.getAbsolutePath()); - - shell.add(new SimpleCommand("chmod " + TorServiceConstants.CHMOD_EXE_VALUE + ' ' + fileBin.getAbsolutePath())).waitForFinish(); - - File fileTest = new File(fileBin.getAbsolutePath()); - log(fileTest.getName() + ": POST: Is binary exec? " + fileTest.canExecute()); - - shell.close(); - } - - return fileBin.canExecute(); - } - - private void showFileTree () - { - - File fileDir = this.getDir("bin", Context.MODE_PRIVATE); - - if (fileDir.exists()) - { - log("checking file tree: " + fileDir.getAbsolutePath()); - printDir (fileDir.getName(), fileDir); - } - else - { - log("app_bin does not exist"); - } - - fileDir = this.getDir("data", Context.MODE_PRIVATE); - if (fileDir.exists()) - { - log("checking file tree: " + fileDir.getAbsolutePath()); - printDir (fileDir.getName(), fileDir); - } - else - { - log ("app_data does not exist"); - } - - - } - - private void printDir (String path, File fileDir) - { - File[] files = fileDir.listFiles(); - - if (files != null && files.length > 0) - { - for (File file : files) - { - - try - { - if (file.isDirectory()) - { - printDir(path + '/' + file.getName(), file); - } - else - { - log(path + '/' + file.getName() + " len:" + file.length() + " exec:" + file.canExecute()); - - } - } - catch (Exception e) - { - log("problem printing out file information"); - } - - } - } - } - - Handler mHandler = new Handler () - { - - @Override - public void handleMessage(Message msg) { - - super.handleMessage(msg); - - String logMsg = msg.getData().getString("log"); - log(logMsg); - } - - }; - - private void log (String msg) - { - Log.d(TAG, msg); - mTextView.append(msg + '\n'); - log.append(msg + '\n'); - } - - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate menu resource file. - getMenuInflater().inflate(R.menu.share_menu, menu); - - // Locate MenuItem with ShareActionProvider - MenuItem item = menu.findItem(R.id.menu_item_share); - - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - - case R.id.menu_item_share: - sendLog(); - return true; - - default: - return super.onOptionsItemSelected(item); - } - } - - private void sendLog () - { - int maxLength = 5000; - - String logShare = null; - - if (log.length() > maxLength) - logShare = log.substring(0, maxLength); - else - logShare = log.toString(); - - Intent sendIntent = new Intent(); - sendIntent.setAction(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_TEXT, logShare); - sendIntent.setType("text/plain"); - startActivity(sendIntent); - } - - -} diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java new file mode 100644 index 0000000..b3583bc --- /dev/null +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -0,0 +1,1196 @@ +/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - https://guardianproject.info */ +/* See LICENSE for licensing information */ + +package org.torproject.android; + +import info.guardianproject.browser.Browser; + +import java.net.URLDecoder; +import java.util.Locale; + +import org.torproject.android.service.TorService; +import org.torproject.android.service.TorServiceConstants; +import org.torproject.android.service.TorServiceUtils; +import org.torproject.android.settings.SettingsPreferences; +import org.torproject.android.ui.ChooseLocaleWizardActivity; +import org.torproject.android.ui.ImageProgressView; +import org.torproject.android.ui.Rotate3dAnimation; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.AlertDialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Configuration; +import android.net.Uri; +import android.net.VpnService; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.RemoteException; +import android.support.v4.content.LocalBroadcastManager; +import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.ActionBarDrawerToggle; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.GestureDetector; +import android.view.GestureDetector.SimpleOnGestureListener; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; +import android.view.View.OnTouchListener; +import android.view.animation.AccelerateInterpolator; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + + +public class OrbotMainActivity extends Activity implements TorConstants, OnLongClickListener, OnTouchListener, OnSharedPreferenceChangeListener +{ + /* Useful UI bits */ + private TextView lblStatus = null; //the main text display widget + private ImageProgressView imgStatus = null; //the main touchable image for activating Orbot + + private MenuItem mItemOnOff = null; + private TextView downloadText = null; + private TextView uploadText = null; + + private Button mBtnBrowser = null; + private Button mBtnVPN = null; + + /* Some tracking bits */ + private int torStatus = TorServiceConstants.STATUS_OFF; //latest status reported from the tor service + + private SharedPreferences mPrefs = null; + + private boolean autoStartFromIntent = false; + + private final static long INIT_DELAY = 100; + + /** Called when the activity is first created. */ + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mPrefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); + mPrefs.registerOnSharedPreferenceChangeListener(this); + + setLocale(); + + doLayout(); + + // appConflictChecker (); + + + // Register to receive messages. + // We are registering an observer (mMessageReceiver) to receive Intents + // with actions named "custom-event-name". + LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, + new IntentFilter("status")); + + LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, + new IntentFilter("log")); + + mHandler.postDelayed(new Runnable () + { + + public void run () + { + startService(TorServiceConstants.CMD_INIT); + } + },INIT_DELAY); + + } + + // Our handler for received Intents. This will be called whenever an Intent + // with an action named "custom-event-name" is broadcasted. + private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { + + + + @Override + public void onReceive(Context context, Intent intent) { + // Get extra data included in the Intent + + if (intent.hasExtra("log")) + { + String log = intent.getStringExtra("log"); + updateStatus(log); + } + else if (intent.hasExtra("up")) + { + long upload = intent.getLongExtra("up",0); + long download = intent.getLongExtra("down",0); + long written = intent.getLongExtra("written",0); + long read = intent.getLongExtra("read",0); + + Message msg = mHandler.obtainMessage(TorServiceConstants.MESSAGE_TRAFFIC_COUNT); + msg.getData().putLong("download", download); + msg.getData().putLong("upload", upload); + msg.getData().putLong("readTotal", read); + msg.getData().putLong("writeTotal", written); + mHandler.sendMessage(msg); + + } + else if (intent.hasExtra("status")) + { + torStatus = intent.getIntExtra("status", TorServiceConstants.STATUS_OFF); + updateStatus(""); + } + + } + }; + + private void startService (String action) + { + + Intent torService = new Intent(this, TorService.class); + torService.setAction(action); + startService(torService); + + } + + private void stopService () + { + + Intent torService = new Intent(this, TorService.class); + stopService(torService); + + } + + private DrawerLayout mDrawer; + private ActionBarDrawerToggle mDrawerToggle; + private Toolbar mToolbar; + + private void doLayout () + { + setContentView(R.layout.layout_main); + + mToolbar = (Toolbar) findViewById(R.id.toolbar); + mToolbar.inflateMenu(R.menu.orbot_main); + mToolbar.setTitle(R.string.app_name); + + mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout); + mDrawerToggle = new ActionBarDrawerToggle( + this, mDrawer, mToolbar, + android.R.string.ok, android.R.string.cancel + ); + + mDrawer.setDrawerListener(mDrawerToggle); + mDrawerToggle.setDrawerIndicatorEnabled(true); + mDrawerToggle.syncState(); + mDrawerToggle.setToolbarNavigationClickListener(new OnClickListener () + { + + @Override + public void onClick(View v) { + + + + } + + + }); + + + lblStatus = (TextView)findViewById(R.id.lblStatus); + imgStatus = (ImageProgressView)findViewById(R.id.imgStatus); + imgStatus.setOnLongClickListener(this); + + downloadText = (TextView)findViewById(R.id.trafficDown); + uploadText = (TextView)findViewById(R.id.trafficUp); + + downloadText.setText(formatCount(0) + " / " + formatTotal(0)); + uploadText.setText(formatCount(0) + " / " + formatTotal(0)); + + // Gesture detection + mGestureDetector = new GestureDetector(this, new MyGestureDetector()); + + mBtnBrowser = (Button)findViewById(R.id.btnBrowser); + mBtnBrowser.setOnClickListener(new View.OnClickListener () + { + + @Override + public void onClick(View v) { + doTorCheck(); + + } + + + }); + + mBtnVPN = (Button)findViewById(R.id.btnVPN); + mBtnVPN.setOnClickListener(new View.OnClickListener () + { + + @Override + public void onClick(View v) { + + startVpnService(); + + } + + + }); + + + } + + GestureDetector mGestureDetector; + + + @Override + public boolean onTouch(View v, MotionEvent event) { + return mGestureDetector.onTouchEvent(event); + + } + + /* + * Create the UI Options Menu (non-Javadoc) + * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu) + */ + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.orbot_main, menu); + + mItemOnOff = menu.getItem(0); + + return true; + } + + /** + private void appConflictChecker () + { + SharedPreferences sprefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); + + boolean showAppConflict = true;//sprefs.getBoolean("pref_show_conflict",true); + + String[] badApps = {"com.sec.msc.nts.android.proxy:com.sec.msc.nts.android.proxy","com.sec.pcw:Samsung Link"}; + + for (String badApp : badApps) + { + String[] badAppParts = badApp.split(":"); + + if (appInstalledOrNot(badAppParts[0])) + { + String msg = getString(R.string.please_disable_this_app_in_android_settings_apps_if_you_are_having_problems_with_orbot_) + badAppParts[1]; + + if (showAppConflict) + showAlert(getString(R.string.app_conflict),msg,true); + + // appendLogTextAndScroll(msg); + } + } + + sprefs.edit().putBoolean("pref_show_conflict", false).commit(); + + }*/ + + + + + private void showAbout () + { + + LayoutInflater li = LayoutInflater.from(this); + View view = li.inflate(R.layout.layout_about, null); + + String version = ""; + + try { + version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName + " (Tor " + TorServiceConstants.BINARY_TOR_VERSION + ")"; + } catch (NameNotFoundException e) { + version = "Version Not Found"; + } + + TextView versionName = (TextView)view.findViewById(R.id.versionName); + versionName.setText(version); + + new AlertDialog.Builder(this) + .setTitle(getString(R.string.button_about)) + .setView(view) + .show(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + super.onOptionsItemSelected(item); + + if (item.getItemId() == R.id.menu_start) + { + + try + { + + if (torStatus == TorServiceConstants.STATUS_OFF) + { + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_stop); + startTor(); + + } + else + { + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_start); + + stopTor(); + stopService (); + + } + + } + catch (RemoteException re) + { + Log.w(TAG, "Unable to start/top Tor from menu UI", re); + } + } + else if (item.getItemId() == R.id.menu_settings) + { + showSettings(); + } + else if (item.getItemId() == R.id.menu_wizard) + { + startActivity(new Intent(this, ChooseLocaleWizardActivity.class)); + + } + else if (item.getItemId() == R.id.menu_exit) + { + //exit app + doExit(); + + + } + else if (item.getItemId() == R.id.menu_about) + { + showAbout(); + + + } + + /** + else if (item.getItemId() == R.id.menu_verify) + { + doTorCheck(); + } + else if (item.getItemId() == R.id.menu_vpn) + { + startVpnService(); + }*/ + + return true; + } + + /** + * This is our attempt to REALLY exit Orbot, and stop the background service + * However, Android doesn't like people "quitting" apps, and/or our code may not + * be quite right b/c no matter what we do, it seems like the TorService still exists + **/ + private void doExit () + { + try { + + //one of the confusing things about all of this code is the multiple + //places where things like "stopTor" are called, both in the Activity and the Service + //not something to tackle in your first iteration, but i thin we can talk about fixing + //terminology but also making sure there are clear distinctions in control + stopTor(); + stopService (); + + + } catch (RemoteException e) { + Log.w(TAG, e); + } + + //Kill all the wizard activities + setResult(RESULT_CLOSE_ALL); + finish(); + + } + + /* (non-Javadoc) + * @see android.app.Activity#onPause() + */ + protected void onPause() { + try + { + super.onPause(); + + if (aDialog != null) + aDialog.dismiss(); + } + catch (IllegalStateException ise) + { + //can happen on exit/shutdown + } + } + + private void doTorCheck () + { + + openBrowser(URL_TOR_CHECK); + + + } + + private void enableHiddenServicePort (int hsPort) + { + + Editor pEdit = mPrefs.edit(); + + String hsPortString = mPrefs.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 = mPrefs.getString("pref_hs_hostname",""); + + while (onionHostname.length() == 0) + { + //we need to stop and start Tor + try { + stopTor(); + + Thread.sleep(3000); //wait three seconds + + startTor(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + onionHostname = mPrefs.getString("pref_hs_hostname",""); + } + + Intent nResult = new Intent(); + nResult.putExtra("hs_host", onionHostname); + setResult(RESULT_OK, nResult); + + } + + + private synchronized void handleIntents () + { + if (getIntent() == null) + return; + + // Get intent, action and MIME type + Intent intent = getIntent(); + String action = intent.getAction(); + String type = intent.getType(); + + if (action == null) + return; + + if (action.equals("org.torproject.android.REQUEST_HS_PORT")) + { + + DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { + + 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; + } + } + }; + + int hsPort = getIntent().getIntExtra("hs_port", -1); + + String requestMsg = getString(R.string.hidden_service_request, hsPort); + 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")) + { + autoStartFromIntent = true; + + try { + startTor(); + + Intent nResult = new Intent(); + + //nResult.putExtra("socks", ); //TODO respond with socks, transport, dns, etc + + setResult(RESULT_OK,nResult); + + } catch (RemoteException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + else if (action.equals(Intent.ACTION_VIEW)) + { + String urlString = intent.getDataString(); + + if (urlString != null) + { + + if (urlString.toLowerCase().startsWith("bridge://")) + + { + String newBridgeValue = urlString.substring(9); //remove the bridge protocol piece + newBridgeValue = URLDecoder.decode(newBridgeValue); //decode the value here + + showAlert("Bridges Updated","Restart Orbot to use this bridge: " + newBridgeValue,false); + + String bridges = mPrefs.getString(TorConstants.PREF_BRIDGES_LIST, null); + + Editor pEdit = mPrefs.edit(); + + if (bridges != null && bridges.trim().length() > 0) + { + if (bridges.indexOf('\n')!=-1) + bridges += '\n' + newBridgeValue; + else + bridges += ',' + newBridgeValue; + } + else + bridges = newBridgeValue; + + pEdit.putString(TorConstants.PREF_BRIDGES_LIST,bridges); //set the string to a preference + pEdit.putBoolean(TorConstants.PREF_BRIDGES_ENABLED,true); + + pEdit.commit(); + + setResult(RESULT_OK); + } + } + } + else + { + + showWizard = mPrefs.getBoolean("show_wizard",showWizard); + + if (showWizard) + { + Editor pEdit = mPrefs.edit(); + pEdit.putBoolean("show_wizard",false); + pEdit.commit(); + showWizard = false; + + startActivity(new Intent(this, ChooseLocaleWizardActivity.class)); + + } + + } + + setIntent(null); + + updateStatus (""); + + } + + private boolean showWizard = true; + + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + doLayout(); + updateStatus(""); + } + + + /* + * Launch the system activity for Uri viewing with the provided url + */ + private void openBrowser(final String browserLaunchUrl) + { + //startIntent("info.guardianproject.browser.Browser",Intent.ACTION_VIEW,Uri.parse(browserLaunchUrl)); + + Intent intentBrowser = new Intent(this, Browser.class); + intentBrowser.setAction(Intent.ACTION_VIEW); + intentBrowser.setData(Uri.parse(browserLaunchUrl)); + startActivity(intentBrowser); + + /** + boolean isOrwebInstalled = appInstalledOrNot("info.guardianproject.browser"); + boolean isTransProxy = mPrefs.getBoolean("pref_transparent", false); + + if (isOrwebInstalled) + { + } + else if (isTransProxy) + { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(browserLaunchUrl)); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + else + { + AlertDialog aDialog = new AlertDialog.Builder(Orbot.this) + .setIcon(R.drawable.onion32) + .setTitle(R.string.install_apps_) + .setMessage(R.string.it_doesn_t_seem_like_you_have_orweb_installed_want_help_with_that_or_should_we_just_open_the_browser_) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener () + { + + @Override + public void onClick(DialogInterface dialog, int which) { + + //prompt to install Orweb + Intent intent = new Intent(Orbot.this,TipsAndTricks.class); + startActivity(intent); + + } + + }) + .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener () + { + + @Override + public void onClick(DialogInterface dialog, int which) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(browserLaunchUrl)); + intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + + } + + }) + .show(); + + }*/ + + } + + private void startIntent (String pkg, String action, Uri data) + { + Intent i; + PackageManager manager = getPackageManager(); + try { + i = manager.getLaunchIntentForPackage(pkg); + if (i == null) + throw new PackageManager.NameNotFoundException(); + i.setAction(action); + i.setData(data); + startActivity(i); + } catch (PackageManager.NameNotFoundException e) { + + } + } + + private boolean appInstalledOrNot(String uri) + { + PackageManager pm = getPackageManager(); + try + { + PackageInfo pi = pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES); + return pi.applicationInfo.enabled; + } + catch (PackageManager.NameNotFoundException e) + { + return false; + } +} + + /* + * Load the basic settings application to display torrc + */ + private void showSettings () + { + + startActivityForResult(new Intent(this, SettingsPreferences.class), 1); + } + + + @Override + protected void onActivityResult(int request, int response, Intent data) { + super.onActivityResult(request, response, data); + + + if (request == 1 && response == RESULT_OK) + { + if (data != null && data.getBooleanExtra("transproxywipe", false)) + { + + boolean result = flushTransProxy(); + + if (result) + { + + Toast.makeText(this, R.string.transparent_proxy_rules_flushed_, Toast.LENGTH_SHORT).show(); + + } + else + { + + Toast.makeText(this, R.string.you_do_not_have_root_access_enabled, Toast.LENGTH_SHORT).show(); + + } + + } + else if (torStatus == TorServiceConstants.STATUS_ON) + { + updateSettings(); + Toast.makeText(this, R.string.you_may_need_to_stop_and_start_orbot_for_settings_change_to_be_enabled_, Toast.LENGTH_SHORT).show(); + + } + } + else if (request == REQUEST_VPN && response == RESULT_OK) + { + startService(TorServiceConstants.CMD_VPN); + } + + } + + private final static int REQUEST_VPN = 8888; + + @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) + public void startVpnService () + { + Intent intent = VpnService.prepare(this); + if (intent != null) { + startActivityForResult(intent,REQUEST_VPN); + } + else + { + startService(TorServiceConstants.CMD_VPN); + + } + } + + private boolean flushTransProxy () + { + startService(TorServiceConstants.CMD_FLUSH); + return true; + } + + private boolean updateSettings () + { + //todo send service command + startService(TorServiceConstants.CMD_UPDATE); + return true; + } + + @Override + protected void onResume() { + super.onResume(); + + mHandler.postDelayed(new Runnable () + { + public void run () + { + + setLocale(); + + handleIntents(); + + } + } + , 500); + + + } + + AlertDialog aDialog = null; + + //general alert dialog for mostly Tor warning messages + //sometimes this can go haywire or crazy with too many error + //messages from Tor, and the user cannot stop or exit Orbot + //so need to ensure repeated error messages are not spamming this method + private void showAlert(String title, String msg, boolean button) + { + try + { + if (aDialog != null && aDialog.isShowing()) + aDialog.dismiss(); + } + catch (Exception e){} //swallow any errors + + if (button) + { + aDialog = new AlertDialog.Builder(OrbotMainActivity.this) + .setIcon(R.drawable.onion32) + .setTitle(title) + .setMessage(msg) + .setPositiveButton(android.R.string.ok, null) + .show(); + } + else + { + aDialog = new AlertDialog.Builder(OrbotMainActivity.this) + .setIcon(R.drawable.onion32) + .setTitle(title) + .setMessage(msg) + .show(); + } + + aDialog.setCanceledOnTouchOutside(true); + } + + private void updateStatus (String torServiceMsg) + { + + //now update the layout_main UI based on the status + if (imgStatus != null) + { + + if (torStatus == TorServiceConstants.STATUS_ON) + { + + imgStatus.setImageResource(R.drawable.toron); + + mBtnBrowser.setEnabled(true); + mBtnVPN.setEnabled(true); + + lblStatus.setText(""); + + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_stop); + + + if (torServiceMsg != null && torServiceMsg.length() > 0) + { + // appendLogTextAndScroll(torServiceMsg); + } + + boolean showFirstTime = mPrefs.getBoolean("connect_first_time",true); + + if (showFirstTime) + { + + Editor pEdit = mPrefs.edit(); + + pEdit.putBoolean("connect_first_time",false); + + pEdit.commit(); + + showAlert(getString(R.string.status_activated),getString(R.string.connect_first_time),true); + + } + + + if (autoStartFromIntent) + { + setResult(RESULT_OK); + finish(); + } + + } + else if (torStatus == TorServiceConstants.STATUS_CONNECTING) + { + + imgStatus.setImageResource(R.drawable.torstarting); + + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_stop); + + if (lblStatus != null && torServiceMsg != null) + if (torServiceMsg.indexOf('%')!=-1) + lblStatus.setText(torServiceMsg); + + + //appendLogTextAndScroll(torServiceMsg); + + + } + else if (torStatus == TorServiceConstants.STATUS_OFF) + { + imgStatus.setImageResource(R.drawable.toroff); + lblStatus.setText(""); + //lblStatus.setText(getString(R.string.status_disabled) + "\n" + getString(R.string.press_to_start)); + + if (mItemOnOff != null) + mItemOnOff.setTitle(R.string.menu_start); + + mBtnBrowser.setEnabled(false); + mBtnVPN.setEnabled(false); + + } + } + + + } + + + + // guess what? this start's Tor! actually no it just requests via the local ITorService to the remote TorService instance + // to start Tor + private void startTor () throws RemoteException + { + + + startService (TorServiceConstants.CMD_START); + torStatus = TorServiceConstants.STATUS_CONNECTING; + +// mTxtOrbotLog.setText(""); + + //here we update the UI which is a bit sloppy and mixed up code wise + //might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense + imgStatus.setImageResource(R.drawable.torstarting); + // lblStatus.setText(getString(R.string.status_starting_up)); + + //we send a message here to the progressDialog i believe, but we can clarify that shortly + Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); + msg.getData().putString(HANDLER_TOR_MSG, getString(R.string.status_starting_up)); + mHandler.sendMessage(msg); + + + + } + + //now we stop Tor! amazing! + private void stopTor () throws RemoteException + { + + startService (TorServiceConstants.CMD_STOP); + torStatus = TorServiceConstants.STATUS_OFF; + Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG); + mHandler.sendMessage(msg); + + } + + /* + * (non-Javadoc) + * @see android.view.View.OnClickListener#onClick(android.view.View) + */ + public boolean onLongClick(View view) { + + try + { + + if (torStatus == TorServiceConstants.STATUS_OFF) + { + + startTor(); + } + else + { + + stopTor(); + stopService (); + + } + + return true; + + } + catch (Exception e) + { + Log.d(TAG,"error onclick",e); + } + + return false; + + } + + + + + +// this is what takes messages or values from the callback threads or other non-mainUI threads +//and passes them back into the main UI thread for display to the user + private Handler mHandler = new Handler() { + + private String lastServiceMsg = null; + + public void handleMessage(Message msg) { + switch (msg.what) { + case TorServiceConstants.STATUS_MSG: + case TorServiceConstants.LOG_MSG: + + String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG); + + if (lastServiceMsg == null || !lastServiceMsg.equals(torServiceMsg)) + { + updateStatus(torServiceMsg); + + lastServiceMsg = torServiceMsg; + } + + break; + case TorServiceConstants.ENABLE_TOR_MSG: + + + updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); + + break; + case TorServiceConstants.DISABLE_TOR_MSG: + + updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); + + break; + + + case TorServiceConstants.MESSAGE_TRAFFIC_COUNT : + + Bundle data = msg.getData(); + DataCount datacount = new DataCount(data.getLong("upload"),data.getLong("download")); + + long totalRead = data.getLong("readTotal"); + long totalWrite = data.getLong("writeTotal"); + + downloadText.setText(formatCount(datacount.Download) + " / " + formatTotal(totalRead)); + uploadText.setText(formatCount(datacount.Upload) + " / " + formatTotal(totalWrite)); + + if (torStatus != TorServiceConstants.STATUS_ON) + { + updateStatus(""); + } + + default: + super.handleMessage(msg); + } + } + + + + }; + + + /** + * Class for interacting with the main interface of the service. + */ + // this is the connection that gets called back when a successfull bind occurs + // we should use this to activity monitor unbind so that we don't have to call + // bindService() a million times + + private void setLocale () + { + + + Configuration config = getResources().getConfiguration(); + String lang = mPrefs.getString(PREF_DEFAULT_LOCALE, ""); + + if (! "".equals(lang) && ! config.locale.getLanguage().equals(lang)) + { + Locale locale = new Locale(lang); + Locale.setDefault(locale); + config.locale = locale; + getResources().updateConfiguration(config, getResources().getDisplayMetrics()); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); + + } + + public class DataCount { + // data uploaded + public long Upload; + // data downloaded + public long Download; + + DataCount(long Upload, long Download){ + this.Upload = Upload; + this.Download = Download; + } + } + + private String formatCount(long count) { + // Converts the supplied argument into a string. + // Under 2Mb, returns "xxx.xKb" + // Over 2Mb, returns "xxx.xxMb" + if (count < 1e6) + return ((float)((int)(count*10/1024))/10 + "kbps"); + return ((float)((int)(count*100/1024/1024))/100 + "mbps"); + + //return count+" kB"; + } + + private String formatTotal(long count) { + // Converts the supplied argument into a string. + // Under 2Mb, returns "xxx.xKb" + // Over 2Mb, returns "xxx.xxMb" + if (count < 1e6) + return ((float)((int)(count*10/1024))/10 + "KB"); + return ((float)((int)(count*100/1024/1024))/100 + "MB"); + + //return count+" kB"; + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + + + } + + private static final float ROTATE_FROM = 0.0f; + private static final float ROTATE_TO = 360.0f*4f;// 3.141592654f * 32.0f; + + public void spinOrbot (float direction) + { + startService (TorServiceConstants.CMD_NEWNYM); + + + Toast.makeText(this, R.string.newnym, Toast.LENGTH_SHORT).show(); + + // Rotate3dAnimation rotation = new Rotate3dAnimation(ROTATE_FROM, ROTATE_TO*direction, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + Rotate3dAnimation rotation = new Rotate3dAnimation(ROTATE_FROM, ROTATE_TO*direction, imgStatus.getWidth()/2f,imgStatus.getWidth()/2f,20f,false); + rotation.setFillAfter(true); + rotation.setInterpolator(new AccelerateInterpolator()); + rotation.setDuration((long) 2*1000); + rotation.setRepeatCount(0); + imgStatus.startAnimation(rotation); + + + } + + class MyGestureDetector extends SimpleOnGestureListener { + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + try { + if (torStatus == TorServiceConstants.STATUS_ON) + { + float direction = 1f; + if (velocityX < 0) + direction = -1f; + spinOrbot (direction); + } + } catch (Exception e) { + // nothing + } + return false; + } + + } + + +} diff --git a/src/org/torproject/android/RandomColorCircleView.java b/src/org/torproject/android/RandomColorCircleView.java deleted file mode 100644 index 6e9a839..0000000 --- a/src/org/torproject/android/RandomColorCircleView.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.torproject.android; - -import java.util.Random; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.View; - -public class RandomColorCircleView extends View -{ - - private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); - - private float initX, initY, radius; - private boolean drawing = false; - - Random rand = new Random(); - - - public RandomColorCircleView(Context context) { - super(context); - // TODO Auto-generated constructor stub - init(); - - } - - public RandomColorCircleView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public RandomColorCircleView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - init(); - } - - private void init(){ - paint.setStyle(Paint.Style.STROKE); - paint.setColor(Color.WHITE); - paint.setAntiAlias(false); - paint.setStrokeWidth(6); - - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), - MeasureSpec.getSize(heightMeasureSpec)); - - } - - int a1 = 30; - int a2 = 255; - - @Override - protected void onDraw(Canvas canvas) { - - super.onDraw(canvas); - - for (int i = 0; i < 20; i++) - { - float r = rand.nextFloat()*255f; - float g = rand.nextFloat()*255f; - float b = rand.nextFloat()*255f; - - paint.setARGB(a1,(int)r,(int)g,(int)b); - - float x = rand.nextFloat() * getWidth(); - float y = rand.nextFloat() * getHeight(); - - float w = rand.nextFloat() * getWidth(); - float h = rand.nextFloat() * getHeight(); - - canvas.drawCircle(x, y, w/2, paint); - - - } - - } - - int a1mod = 1; - - public void updateAlpha () - { - a1 += a1mod; - - if (a1 > 255 || a1 < 0) - a1mod *= -1; - - - } - - /* - @Override - public boolean onTouchEvent(MotionEvent event) { - - - int action = event.getAction(); - if (action==MotionEvent.ACTION_MOVE){ - float x = event.getX(); - float y = event.getY(); - - // radius = (float) Math.sqrt(Math.pow(x-initX, 2) + Math.pow(y-initY, 2)); - //updateAlpha(); - - a1 = (int)(255*(y/((float)getHeight()))); - - } - else if (action==MotionEvent.ACTION_DOWN){ - initX = event.getX(); - initY = event.getY(); - radius = 1; - drawing = true; - - - } - else if (action==MotionEvent.ACTION_UP){ - drawing = false; - - - } - - return true; - - }*/ - -} \ No newline at end of file diff --git a/src/org/torproject/android/Rotate3dAnimation.java b/src/org/torproject/android/Rotate3dAnimation.java deleted file mode 100644 index 10bb52e..0000000 --- a/src/org/torproject/android/Rotate3dAnimation.java +++ /dev/null @@ -1,76 +0,0 @@ -package org.torproject.android; - -import android.graphics.Camera; -import android.graphics.Matrix; -import android.view.animation.Animation; -import android.view.animation.Transformation; - -/** - * An animation that rotates the view on the Y axis between two specified angles. - * This animation also adds a translation on the Z axis (depth) to improve the effect. - */ -public class Rotate3dAnimation extends Animation { - private final float mFromDegrees; - private final float mToDegrees; - private final float mCenterX; - private final float mCenterY; - private final float mDepthZ; - private final boolean mReverse; - private Camera mCamera; - - /** - * Creates a new 3D rotation on the Y axis. The rotation is defined by its - * start angle and its end angle. Both angles are in degrees. The rotation - * is performed around a center point on the 2D space, definied by a pair - * of X and Y coordinates, called centerX and centerY. When the animation - * starts, a translation on the Z axis (depth) is performed. The length - * of the translation can be specified, as well as whether the translation - * should be reversed in time. - * - * @param fromDegrees the start angle of the 3D rotation - * @param toDegrees the end angle of the 3D rotation - * @param centerX the X center of the 3D rotation - * @param centerY the Y center of the 3D rotation - * @param reverse true if the translation should be reversed, false otherwise - */ - public Rotate3dAnimation(float fromDegrees, float toDegrees, - float centerX, float centerY, float depthZ, boolean reverse) { - mFromDegrees = fromDegrees; - mToDegrees = toDegrees; - mCenterX = centerX; - mCenterY = centerY; - mDepthZ = depthZ; - mReverse = reverse; - } - - @Override - public void initialize(int width, int height, int parentWidth, int parentHeight) { - super.initialize(width, height, parentWidth, parentHeight); - mCamera = new Camera(); - } - - @Override - protected void applyTransformation(float interpolatedTime, Transformation t) { - final float fromDegrees = mFromDegrees; - float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime); - - final float centerX = mCenterX; - final float centerY = mCenterY; - final Camera camera = mCamera; - - final Matrix matrix = t.getMatrix(); - - camera.save(); - if (mReverse) { - camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); - } else { - camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); - } - camera.rotateY(degrees); - camera.getMatrix(matrix); - camera.restore(); - - matrix.preTranslate(-centerX, -centerY); - matrix.postTranslate(centerX, centerY); - } -} diff --git a/src/org/torproject/android/Utils.java b/src/org/torproject/android/Utils.java deleted file mode 100644 index f5f2ea5..0000000 --- a/src/org/torproject/android/Utils.java +++ /dev/null @@ -1,100 +0,0 @@ -/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ -/* See LICENSE for licensing information */ - - -package org.torproject.android; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; - -public class Utils { - - - public static String readString (InputStream stream) - { - String line = null; - - StringBuffer out = new StringBuffer(); - - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); - - while ((line = reader.readLine()) != null) - { - out.append(line); - out.append('\n'); - - } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return out.toString(); - - } - /* - * Load the log file text - */ - public static String loadTextFile (String path) - { - String line = null; - - StringBuffer out = new StringBuffer(); - - try { - BufferedReader reader = new BufferedReader((new FileReader(new File(path)))); - - while ((line = reader.readLine()) != null) - { - out.append(line); - out.append('\n'); - - } - - reader.close(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - return out.toString(); - - } - - - /* - * Load the log file text - */ - public static boolean saveTextFile (String path, String contents) - { - - try { - - FileWriter writer = new FileWriter( path, false ); - writer.write( contents ); - - writer.close(); - - - - return true; - - } catch (IOException e) { - // Log.d(TAG, "error writing file: " + path, e); - e.printStackTrace(); - return false; - } - - - - } - - - -} diff --git a/src/org/torproject/android/pluto/PlutoFactory.java b/src/org/torproject/android/pluto/PlutoFactory.java new file mode 100644 index 0000000..094bc5e --- /dev/null +++ b/src/org/torproject/android/pluto/PlutoFactory.java @@ -0,0 +1,14 @@ +package org.torproject.android.pluto; + +public class PlutoFactory { + + + //load pluto.properties from res/raw/pluto.properties + + //ensure the PT binaries are installed and exe + + //expose the installed PT's via a simple factory instance interface .getPlutoInstance("obfs3") + + //return instance with interface for getting exe path, directly starting/stopping, monitoring status, etc + +} diff --git a/src/org/torproject/android/pluto/PlutoInstaller.java b/src/org/torproject/android/pluto/PlutoInstaller.java new file mode 100644 index 0000000..4c312c4 --- /dev/null +++ b/src/org/torproject/android/pluto/PlutoInstaller.java @@ -0,0 +1,194 @@ +/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ +/* See LICENSE for licensing information */ + +package org.torproject.android.pluto; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.StringBufferInputStream; +import java.util.ArrayList; +import java.util.concurrent.TimeoutException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.sufficientlysecure.rootcommands.Shell; +import org.sufficientlysecure.rootcommands.command.SimpleCommand; +import org.torproject.android.R; +import org.torproject.android.TorConstants; + +import android.content.Context; +import android.os.Build; +import android.util.Log; + +public class PlutoInstaller { + + + private File installFolder; + private Context context; + + private final static int FILE_WRITE_BUFFER_SIZE = 1024; + private final static String CHMOD_EXE_VALUE = "770"; + private final static String COMMAND_RM_FORCE = "rm -f "; + + public PlutoInstaller (Context context, File installFolder) + { + this.installFolder = installFolder; + this.context = context; + } + + public boolean installBinaries () throws Exception + { + + InputStream is; + File outFile; + + installFolder.mkdirs(); + + Shell shell = Shell.startShell(new ArrayList<String>(),installFolder.getAbsolutePath()); + + String ptAsset = null; + + is = context.getResources().openRawResource(R.raw.obfsclient); + + outFile = new File(installFolder, ptAsset); + shell.add(new SimpleCommand(COMMAND_RM_FORCE + outFile.getAbsolutePath())).waitForFinish(); + streamToFile(is,outFile, false, true); + + enableBinExec (outFile); + + return true; + } + + private boolean enableBinExec (File fileBin) throws Exception + { + + if (!fileBin.canExecute()) + { + Shell shell = Shell.startShell(); + shell.add(new SimpleCommand("chmod " + CHMOD_EXE_VALUE + ' ' + fileBin.getCanonicalPath())).waitForFinish(); + + File fileTest = new File(fileBin.getCanonicalPath()); + shell.close(); + } + + return fileBin.canExecute(); + } + + + /* + * Write the inputstream contents to the file + */ + public static boolean streamToFile(InputStream stm, File outFile, boolean append, boolean zip) throws IOException + + { + byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE]; + + int bytecount; + + OutputStream stmOut = new FileOutputStream(outFile.getAbsolutePath(), append); + ZipInputStream zis = null; + + if (zip) + { + zis = new ZipInputStream(stm); + ZipEntry ze = zis.getNextEntry(); + stm = zis; + + } + + while ((bytecount = stm.read(buffer)) > 0) + { + + stmOut.write(buffer, 0, bytecount); + + } + + stmOut.close(); + stm.close(); + + if (zis != null) + zis.close(); + + + return true; + + } + + //copy the file from inputstream to File output - alternative impl + public static void copyFile (InputStream is, File outputFile) + { + + try { + outputFile.createNewFile(); + DataOutputStream out = new DataOutputStream(new FileOutputStream(outputFile)); + DataInputStream in = new DataInputStream(is); + + int b = -1; + byte[] data = new byte[1024]; + + while ((b = in.read(data)) != -1) { + out.write(data); + } + + if (b == -1); //rejoice + + // + out.flush(); + out.close(); + in.close(); + // chmod? + + + + } catch (IOException ex) { + Log.e(TorConstants.TAG, "error copying binary", ex); + } + + } + + + + + /** + * Copies a raw resource file, given its ID to the given location + * @param ctx context + * @param resid resource id + * @param file destination file + * @param mode file permissions (E.g.: "755") + * @throws IOException on error + * @throws InterruptedException when interrupted + */ + public static void copyRawFile(Context ctx, int resid, File file, String mode, boolean isZipd) throws IOException, InterruptedException + { + final String abspath = file.getAbsolutePath(); + // Write the iptables binary + final FileOutputStream out = new FileOutputStream(file); + InputStream is = ctx.getResources().openRawResource(resid); + + if (isZipd) + { + ZipInputStream zis = new ZipInputStream(is); + ZipEntry ze = zis.getNextEntry(); + is = zis; + } + + byte buf[] = new byte[1024]; + int len; + while ((len = is.read(buf)) > 0) { + out.write(buf, 0, len); + } + out.close(); + is.close(); + // Change the permissions + Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor(); + } + + + +} diff --git a/src/org/torproject/android/pluto/PlutoInstance.java b/src/org/torproject/android/pluto/PlutoInstance.java new file mode 100644 index 0000000..4585083 --- /dev/null +++ b/src/org/torproject/android/pluto/PlutoInstance.java @@ -0,0 +1,9 @@ +package org.torproject.android.pluto; + +import java.io.File; + +public class PlutoInstance { + + public String name; + public File fileBinary; +} diff --git a/src/org/torproject/android/service/HiddenServiceManager.java b/src/org/torproject/android/service/HiddenServiceManager.java new file mode 100644 index 0000000..6b0d32d --- /dev/null +++ b/src/org/torproject/android/service/HiddenServiceManager.java @@ -0,0 +1,25 @@ +package org.torproject.android.service; + + +//list view with add/remove hidden services - user is prompted for port + +public class HiddenServiceManager { + +} +/* + * + * ## Once you have configured a hidden service, you can look at the +## contents of the file ".../hidden_service/hostname" for the address +## to tell people. +## +## HiddenServicePort x y:z says to redirect requests on port x to the +## address y:z. + +#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/hidden_service/ +#HiddenServicePort 80 127.0.0.1:80 + +#HiddenServiceDir @LOCALSTATEDIR@/lib/tor/other_hidden_service/ +#HiddenServicePort 80 127.0.0.1:80 +#HiddenServicePort 22 127.0.0.1:22 +*/ + diff --git a/src/org/torproject/android/service/OnBootReceiver.java b/src/org/torproject/android/service/OnBootReceiver.java new file mode 100644 index 0000000..ef40619 --- /dev/null +++ b/src/org/torproject/android/service/OnBootReceiver.java @@ -0,0 +1,39 @@ +package org.torproject.android.service; + + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; + +public class OnBootReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + + SharedPreferences prefs = TorServiceUtils.getSharedPrefs(context.getApplicationContext()); + + boolean startOnBoot = prefs.getBoolean("pref_start_boot",true); + + if (startOnBoot) + { + startService("init",context); + startService("start",context); + } + + } + + + private void startService (String action, Context context) + { + + Intent torService = new Intent(context, TorService.class); + torService.setAction(action); + context.startService(torService); + + + } + + +} + diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 63bf0d5..d9a2fd5 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -47,10 +47,9 @@ import org.json.JSONArray; import org.json.JSONObject; import org.sufficientlysecure.rootcommands.Shell; import org.sufficientlysecure.rootcommands.command.SimpleCommand; -import org.torproject.android.Orbot; +import org.torproject.android.OrbotMainActivity; import org.torproject.android.R; import org.torproject.android.TorConstants; -import org.torproject.android.Utils; import org.torproject.android.settings.AppManager; import org.torproject.android.settings.TorifiedApp; import org.torproject.android.vpn.OrbotVpnService; @@ -241,7 +240,7 @@ public class TorService extends Service implements TorServiceConstants, TorConst { //Reusable code. - Intent intent = new Intent(TorService.this, Orbot.class); + Intent intent = new Intent(TorService.this, OrbotMainActivity.class); PendingIntent pendIntent = PendingIntent.getActivity(TorService.this, 0, intent, 0);
if (mNotifyBuilder == null) diff --git a/src/org/torproject/android/service/Utils.java b/src/org/torproject/android/service/Utils.java new file mode 100644 index 0000000..a89e03f --- /dev/null +++ b/src/org/torproject/android/service/Utils.java @@ -0,0 +1,100 @@ +/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ +/* See LICENSE for licensing information */ + + +package org.torproject.android.service; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +public class Utils { + + + public static String readString (InputStream stream) + { + String line = null; + + StringBuffer out = new StringBuffer(); + + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + + while ((line = reader.readLine()) != null) + { + out.append(line); + out.append('\n'); + + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return out.toString(); + + } + /* + * Load the log file text + */ + public static String loadTextFile (String path) + { + String line = null; + + StringBuffer out = new StringBuffer(); + + try { + BufferedReader reader = new BufferedReader((new FileReader(new File(path)))); + + while ((line = reader.readLine()) != null) + { + out.append(line); + out.append('\n'); + + } + + reader.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return out.toString(); + + } + + + /* + * Load the log file text + */ + public static boolean saveTextFile (String path, String contents) + { + + try { + + FileWriter writer = new FileWriter( path, false ); + writer.write( contents ); + + writer.close(); + + + + return true; + + } catch (IOException e) { + // Log.d(TAG, "error writing file: " + path, e); + e.printStackTrace(); + return false; + } + + + + } + + + +} diff --git a/src/org/torproject/android/ui/ChooseLocaleWizardActivity.java b/src/org/torproject/android/ui/ChooseLocaleWizardActivity.java new file mode 100644 index 0000000..1858f66 --- /dev/null +++ b/src/org/torproject/android/ui/ChooseLocaleWizardActivity.java @@ -0,0 +1,136 @@ +package org.torproject.android.ui; + +import java.util.Locale; + +import org.torproject.android.R; +import org.torproject.android.TorConstants; +import org.torproject.android.service.TorServiceUtils; + +import android.app.Activity; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.content.res.Configuration; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ListView; +import android.widget.Toast; + +public class ChooseLocaleWizardActivity extends Activity implements TorConstants { + + private int flag = 0; + private ListView listLocales; + + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + } + + @Override + protected void onStart() { + + super.onStart(); + setContentView(R.layout.layout_wizard_locale); + + + listLocales = (ListView)findViewById(R.id.wizard_locale_list); + Button next = ((Button)findViewById(R.id.btnWizard2)); + // next.setEnabled(false); + + String[] strLangs = getResources().getStringArray(R.array.languages); + strLangs[0] = Locale.getDefault().getDisplayName(); + ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, strLangs); + listLocales.setAdapter(adapter); + + listLocales.setSelection(0); + + + listLocales.setOnItemClickListener(new OnItemClickListener() { + + + @Override + public void onItemClick(AdapterView<?> arg0, View arg1, + int arg2, long arg3) { + + setLocalePref(arg2); + finish(); + startActivity(new Intent(ChooseLocaleWizardActivity.this, LotsaText.class)); + + } + }); + + next.setOnClickListener(new View.OnClickListener() { + + public void onClick(View v) { + setLocalePref(0); + finish(); + startActivity(new Intent(ChooseLocaleWizardActivity.this, LotsaText.class)); + + } + }); + + + + } + + private void setLocalePref(int selId) + { + + SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); + + Configuration config = getResources().getConfiguration(); + + String[] localeVals = getResources().getStringArray(R.array.languages_values); + + String lang = localeVals[selId]; + + Editor pEdit = prefs.edit(); + pEdit.putString(PREF_DEFAULT_LOCALE, lang); + pEdit.commit(); + Locale locale = null; + + if (lang.equals("xx")) + { + locale = Locale.getDefault(); + + } + else + locale = new Locale(lang); + + Locale.setDefault(locale); + config.locale = locale; + getResources().updateConfiguration(config, getResources().getDisplayMetrics()); + + + + + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + + } + + //Code to override the back button! + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if(keyCode == KeyEvent.KEYCODE_BACK){ + Toast.makeText(getApplicationContext(), R.string.wizard_exit_at_first_screen_toast, Toast.LENGTH_SHORT).show(); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/org/torproject/android/ui/ImageProgressView.java b/src/org/torproject/android/ui/ImageProgressView.java new file mode 100644 index 0000000..641c444 --- /dev/null +++ b/src/org/torproject/android/ui/ImageProgressView.java @@ -0,0 +1,78 @@ +package org.torproject.android.ui; + +import java.util.Random; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; + +public class ImageProgressView extends ImageView +{ + + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private float progress = 0f; // 0 to 1 + + private RectF circle; + + public ImageProgressView(Context context) { + super(context); + // TODO Auto-generated constructor stub + init(); + + } + + public ImageProgressView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public ImageProgressView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + init(); + } + + private void init(){ + paint.setStyle(Paint.Style.STROKE); + paint.setColor(Color.GREEN); + paint.setAntiAlias(true); + paint.setStrokeWidth(20); + + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), + MeasureSpec.getSize(heightMeasureSpec)); + + } + + @Override + protected void onDraw(Canvas canvas) { + + super.onDraw(canvas); + + if (circle == null) + { + circle = new RectF(getWidth()/2,getHeight()/2+getHeight()/8, getWidth()/3,getHeight()/3); + } + + float sweepAngle = 360f * progress; + + canvas.drawArc(circle, 0, sweepAngle, true, paint); + + } + + + + +} \ No newline at end of file diff --git a/src/org/torproject/android/ui/LotsaText.java b/src/org/torproject/android/ui/LotsaText.java new file mode 100644 index 0000000..5fdaa57 --- /dev/null +++ b/src/org/torproject/android/ui/LotsaText.java @@ -0,0 +1,137 @@ +package org.torproject.android.ui; + +import org.torproject.android.R; +import org.torproject.android.TorConstants; +import org.torproject.android.service.TorServiceUtils; + +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.view.KeyEvent; +import android.view.View; +import android.widget.Button; +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 = TorServiceUtils.getSharedPrefs(getApplicationContext()); + + boolean wizardScreen1 = prefs.getBoolean("wizardscreen1",true); + if(wizardScreen1) + stepOne(); + else + stepTwo(); + + } + + @Override + protected void onResume() { + super.onResume(); + + + } + + private void stepOne() { + + SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); + + 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); + + setTitle(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)); + + btn1.setVisibility(Button.INVISIBLE); + + btn2.setOnClickListener(new View.OnClickListener() { + + public void onClick(View v) { + stepTwo(); + } + }); + + } + + private void stepTwo() { + + SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); + + 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); + + setTitle(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)); + + btn1.setVisibility(Button.VISIBLE); + + + btn1.setOnClickListener(new View.OnClickListener() { + + public void onClick(View v) { + + stepOne(); + } + }); + + btn2.setOnClickListener(new View.OnClickListener() { + + public void onClick(View v) { + finish(); + startActivity(new Intent(LotsaText.this, TipsAndTricks.class)); + } + }); + + } + + //Code to override the back button! + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if(keyCode == KeyEvent.KEYCODE_BACK){ + finish(); + startActivity(new Intent(getBaseContext(), ChooseLocaleWizardActivity.class)); + return true; + } + return true; + } + +} \ No newline at end of file diff --git a/src/org/torproject/android/ui/OrbotDiagnosticsActivity.java b/src/org/torproject/android/ui/OrbotDiagnosticsActivity.java new file mode 100644 index 0000000..3f72d16 --- /dev/null +++ b/src/org/torproject/android/ui/OrbotDiagnosticsActivity.java @@ -0,0 +1,337 @@ +package org.torproject.android.ui; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; + +import org.sufficientlysecure.rootcommands.Shell; +import org.sufficientlysecure.rootcommands.command.SimpleCommand; +import org.torproject.android.R; +import org.torproject.android.R.id; +import org.torproject.android.R.layout; +import org.torproject.android.R.menu; +import org.torproject.android.R.raw; +import org.torproject.android.service.TorResourceInstaller; +import org.torproject.android.service.TorServiceConstants; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Message; +import android.os.StatFs; +import android.text.format.Formatter; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.widget.TextView; + + +public class OrbotDiagnosticsActivity extends Activity { + + private TextView mTextView = null; + private final static String TAG = "OrbotDiag"; + private StringBuffer log = new StringBuffer(); + Process mProcess; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.layout_diag); + + mTextView = (TextView)findViewById(R.id.diaglog); + + } + + private String getFreeStorage () + { + File path = Environment.getDataDirectory(); + StatFs stat = new StatFs(path.getPath()); + long blockSize = stat.getBlockSize(); + long availableBlocks = stat.getAvailableBlocks(); + return Formatter.formatFileSize(this, availableBlocks * blockSize); + } + + @Override + protected void onPause() { + super.onPause(); + + stopTor(); + } + + @Override + protected void onDestroy() { + + super.onDestroy(); + + } + + private void stopTor () + { + File appBinHome = this.getDir("bin", Context.MODE_PRIVATE); + + File fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY); + + if (mProcess != null) + mProcess.destroy(); + + + } + + + + @Override + protected void onResume() { + super.onResume(); + + + log("Hello, Orbot!"); + + try + { + log(android.os.Build.DEVICE); + log(android.os.Build.HARDWARE); + log(android.os.Build.MANUFACTURER); + log(android.os.Build.MODEL); + log(android.os.Build.VERSION.CODENAME); + log(android.os.Build.VERSION.RELEASE); + } + catch (Exception e) + { + log("error getting device info"); + } + + showFileTree (); + + runTorTest(); + } + + private void runTorTest () + { + try + { + File appBinHome = this.getDir("bin", Context.MODE_PRIVATE); + File appDataHome = this.getDir("data", Context.MODE_PRIVATE); + + File fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY); + enableBinExec (fileTor, appBinHome); + + InputStream is = getResources().openRawResource(R.raw.torrc); + File fileTorrc = new File(appBinHome, TorServiceConstants.TORRC_ASSET_KEY + "diag"); + TorResourceInstaller.streamToFile(is,fileTorrc, false, false); + + /** + ArrayList<String> alEnv = new ArrayList<String>(); + alEnv.add("HOME=" + appBinHome.getAbsolutePath()); + Shell shell = Shell.startShell(alEnv,appBinHome.getAbsolutePath()); + SimpleCommand cmdTor = new SimpleCommand(fileTor.getAbsolutePath() + " DataDirectory " + appDataHome.getAbsolutePath() + " -f " + fileTorrc.getAbsolutePath()); + shell.add(cmdTor); + **/ + + String cmd = fileTor.getAbsolutePath() + " DataDirectory " + appDataHome.getAbsolutePath() + " -f " + fileTorrc.getAbsolutePath(); + + log ("Executing command> " + cmd); + + mProcess = Runtime.getRuntime().exec(cmd); + + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream())); + StreamGobbler sg = new StreamGobbler(); + sg.reader = bufferedReader; + sg.process = mProcess; + new Thread(sg).start(); + + if (mProcess.getErrorStream() != null) + { + bufferedReader = new BufferedReader(new InputStreamReader(mProcess.getErrorStream())); + sg = new StreamGobbler(); + sg.reader = bufferedReader; + sg.process = mProcess; + new Thread(sg).start(); + } + + + } + catch (Exception e) + { + Log.d(TAG,"runTorTest exception",e); + } + + } + + class StreamGobbler implements Runnable + { + BufferedReader reader; + Process process; + + public void run () + { + String line = null; + try { + while ( (line = reader.readLine()) != null) + { + Message msg = mHandler.obtainMessage(0); + msg.getData().putString("log", line); + mHandler.sendMessage(msg); + } + + } catch (IOException e) { + Log.d(TAG, "error reading line",e); + } + + //log("Tor exit code=" + process.exitValue() + ";"); + + } + } + + private boolean enableBinExec (File fileBin, File appBinHome) throws Exception + { + + log(fileBin.getName() + ": PRE: Is binary exec? " + fileBin.canExecute()); + + if (!fileBin.canExecute()) + { + log("(re)Setting permission on binary: " + fileBin.getAbsolutePath()); + Shell shell = Shell.startShell(new ArrayList<String>(), appBinHome.getAbsolutePath()); + + shell.add(new SimpleCommand("chmod " + TorServiceConstants.CHMOD_EXE_VALUE + ' ' + fileBin.getAbsolutePath())).waitForFinish(); + + File fileTest = new File(fileBin.getAbsolutePath()); + log(fileTest.getName() + ": POST: Is binary exec? " + fileTest.canExecute()); + + shell.close(); + } + + return fileBin.canExecute(); + } + + private void showFileTree () + { + + File fileDir = this.getDir("bin", Context.MODE_PRIVATE); + + if (fileDir.exists()) + { + log("checking file tree: " + fileDir.getAbsolutePath()); + printDir (fileDir.getName(), fileDir); + } + else + { + log("app_bin does not exist"); + } + + fileDir = this.getDir("data", Context.MODE_PRIVATE); + if (fileDir.exists()) + { + log("checking file tree: " + fileDir.getAbsolutePath()); + printDir (fileDir.getName(), fileDir); + } + else + { + log ("app_data does not exist"); + } + + + } + + private void printDir (String path, File fileDir) + { + File[] files = fileDir.listFiles(); + + if (files != null && files.length > 0) + { + for (File file : files) + { + + try + { + if (file.isDirectory()) + { + printDir(path + '/' + file.getName(), file); + } + else + { + log(path + '/' + file.getName() + " len:" + file.length() + " exec:" + file.canExecute()); + + } + } + catch (Exception e) + { + log("problem printing out file information"); + } + + } + } + } + + Handler mHandler = new Handler () + { + + @Override + public void handleMessage(Message msg) { + + super.handleMessage(msg); + + String logMsg = msg.getData().getString("log"); + log(logMsg); + } + + }; + + private void log (String msg) + { + Log.d(TAG, msg); + mTextView.append(msg + '\n'); + log.append(msg + '\n'); + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate menu resource file. + getMenuInflater().inflate(R.menu.share_menu, menu); + + // Locate MenuItem with ShareActionProvider + MenuItem item = menu.findItem(R.id.menu_item_share); + + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + + case R.id.menu_item_share: + sendLog(); + return true; + + default: + return super.onOptionsItemSelected(item); + } + } + + private void sendLog () + { + int maxLength = 5000; + + String logShare = null; + + if (log.length() > maxLength) + logShare = log.substring(0, maxLength); + else + logShare = log.toString(); + + Intent sendIntent = new Intent(); + sendIntent.setAction(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_TEXT, logShare); + sendIntent.setType("text/plain"); + startActivity(sendIntent); + } + + +} diff --git a/src/org/torproject/android/ui/OrbotLogActivity.java b/src/org/torproject/android/ui/OrbotLogActivity.java new file mode 100644 index 0000000..ae83b77 --- /dev/null +++ b/src/org/torproject/android/ui/OrbotLogActivity.java @@ -0,0 +1,75 @@ +/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - https://guardianproject.info */ +/* See LICENSE for licensing information */ + +package org.torproject.android.ui; + +import org.torproject.android.TorConstants; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; + + +public class OrbotLogActivity extends Activity implements TorConstants +{ + + /** Called when the activity is first created. */ + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + doLayout(); + LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, + new IntentFilter("log")); + + + } + + // Our handler for received Intents. This will be called whenever an Intent + // with an action named "custom-event-name" is broadcasted. + private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { + + + + @Override + public void onReceive(Context context, Intent intent) { + // Get extra data included in the Intent + + if (intent.hasExtra("log")) + { + String log = intent.getStringExtra("log"); + updateStatus(log); + } + + + } + }; + + + + private void doLayout () + { + + + } + + + private void updateStatus(String log) + { + + } + + + @Override + protected void onDestroy() { + super.onDestroy(); + LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); + + } + + + +} diff --git a/src/org/torproject/android/ui/Rotate3dAnimation.java b/src/org/torproject/android/ui/Rotate3dAnimation.java new file mode 100644 index 0000000..7829d2d --- /dev/null +++ b/src/org/torproject/android/ui/Rotate3dAnimation.java @@ -0,0 +1,76 @@ +package org.torproject.android.ui; + +import android.graphics.Camera; +import android.graphics.Matrix; +import android.view.animation.Animation; +import android.view.animation.Transformation; + +/** + * An animation that rotates the view on the Y axis between two specified angles. + * This animation also adds a translation on the Z axis (depth) to improve the effect. + */ +public class Rotate3dAnimation extends Animation { + private final float mFromDegrees; + private final float mToDegrees; + private final float mCenterX; + private final float mCenterY; + private final float mDepthZ; + private final boolean mReverse; + private Camera mCamera; + + /** + * Creates a new 3D rotation on the Y axis. The rotation is defined by its + * start angle and its end angle. Both angles are in degrees. The rotation + * is performed around a center point on the 2D space, definied by a pair + * of X and Y coordinates, called centerX and centerY. When the animation + * starts, a translation on the Z axis (depth) is performed. The length + * of the translation can be specified, as well as whether the translation + * should be reversed in time. + * + * @param fromDegrees the start angle of the 3D rotation + * @param toDegrees the end angle of the 3D rotation + * @param centerX the X center of the 3D rotation + * @param centerY the Y center of the 3D rotation + * @param reverse true if the translation should be reversed, false otherwise + */ + public Rotate3dAnimation(float fromDegrees, float toDegrees, + float centerX, float centerY, float depthZ, boolean reverse) { + mFromDegrees = fromDegrees; + mToDegrees = toDegrees; + mCenterX = centerX; + mCenterY = centerY; + mDepthZ = depthZ; + mReverse = reverse; + } + + @Override + public void initialize(int width, int height, int parentWidth, int parentHeight) { + super.initialize(width, height, parentWidth, parentHeight); + mCamera = new Camera(); + } + + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + final float fromDegrees = mFromDegrees; + float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime); + + final float centerX = mCenterX; + final float centerY = mCenterY; + final Camera camera = mCamera; + + final Matrix matrix = t.getMatrix(); + + camera.save(); + if (mReverse) { + camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); + } else { + camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime)); + } + camera.rotateY(degrees); + camera.getMatrix(matrix); + camera.restore(); + + matrix.preTranslate(-centerX, -centerY); + matrix.postTranslate(centerX, centerY); + } +} diff --git a/src/org/torproject/android/ui/TipsAndTricks.java b/src/org/torproject/android/ui/TipsAndTricks.java new file mode 100644 index 0000000..33548f4 --- /dev/null +++ b/src/org/torproject/android/ui/TipsAndTricks.java @@ -0,0 +1,248 @@ +package org.torproject.android.ui; + +import org.torproject.android.OrbotMainActivity; +import org.torproject.android.R; +import org.torproject.android.TorConstants; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.TextView; + +public class TipsAndTricks extends Activity implements TorConstants { + + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + } + + @Override + protected void onStart() { + + super.onStart(); + setContentView(R.layout.layout_wizard_tips); + + stepFive(); + + } + + @Override + protected void onResume() { + super.onResume(); + + + } + + void stepFive(){ + + + String title = getString(R.string.wizard_tips_title); + + setTitle(title); + + Button btnLink = (Button)findViewById(R.id.WizardRootButtonInstallGibberbot); + + btnLink.setOnClickListener(new OnClickListener() { + + public void onClick(View view) { + + String url = getString(R.string.gibberbot_apk_url); + finish(); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + btnLink = (Button)findViewById(R.id.WizardRootButtonInstallOrweb); + + btnLink.setOnClickListener(new OnClickListener() { + + public void onClick(View view) { + + String url = getString(R.string.orweb_apk_url); + finish(); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + btnLink = (Button)findViewById(R.id.WizardRootButtonInstallDuckgo); + + btnLink.setOnClickListener(new OnClickListener() { + + public void onClick(View view) { + + String url = getString(R.string.duckgo_apk_url); + finish(); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + btnLink = (Button)findViewById(R.id.WizardRootButtonInstallFirefox); + + btnLink.setOnClickListener(new OnClickListener() { + + public void onClick(View view) { + + String url = getString(R.string.proxymob_setup_url); + finish(); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + btnLink = (Button)findViewById(R.id.WizardRootButtonInstallTwitter); + + btnLink.setOnClickListener(new OnClickListener() { + + public void onClick(View view) { + + String url = getString(R.string.twitter_setup_url); + finish(); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + btnLink = (Button)findViewById(R.id.WizardRootButtonInstallStoryMaker); + + btnLink.setOnClickListener(new OnClickListener() { + + public void onClick(View view) { + + String url = getString(R.string.story_maker_url); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + btnLink = (Button)findViewById(R.id.WizardRootButtonInstallMartus); + + btnLink.setOnClickListener(new OnClickListener() { + + public void onClick(View view) { + + String url = getString(R.string.martus_url); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + + } + }); + + + btnLink = (Button)findViewById(R.id.WizardRootButtonGooglePlay); + + btnLink.setOnClickListener(new OnClickListener() { + + public void onClick(View view) { + + String url = getString(R.string.wizard_tips_play_url); + 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() { + + public void onClick(View v) { + finish(); + startActivityForResult(new Intent(TipsAndTricks.this, LotsaText.class), 1); + } + }); + + next.setOnClickListener(new View.OnClickListener() { + + public void onClick(View v) { + showWizardFinal(); + } + }); + + } + + private void showWizardFinal () + { + setContentView(R.layout.scrollingtext_buttons_view); + String title = getString(R.string.wizard_final); + String msg = getString(R.string.wizard_final_msg); + + setTitle(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)); + + btn2.setText(getString(R.string.btn_finish)); + btn1.setVisibility(Button.VISIBLE); + + btn1.setOnClickListener(new View.OnClickListener() { + + public void onClick(View v) { + finish(); + startActivity(new Intent(TipsAndTricks.this, LotsaText.class)); + } + }); + + btn2.setOnClickListener(new View.OnClickListener() { + + public void onClick(View v) { + finish(); + } + }); + } + + //Code to override the back button! + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if(keyCode == KeyEvent.KEYCODE_BACK){ + finish(); + startActivity(new Intent(getBaseContext(), LotsaText.class)); + return true; + } + return false; + } + + /* + 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/vpn/OrbotVpnService.java b/src/org/torproject/android/vpn/OrbotVpnService.java index 443bc78..e5b9668 100644 --- a/src/org/torproject/android/vpn/OrbotVpnService.java +++ b/src/org/torproject/android/vpn/OrbotVpnService.java @@ -41,13 +41,13 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { private PendingIntent mConfigureIntent;
private Handler mHandler; - private Thread mThreadProxy; private Thread mThreadVPN;
private String mSessionName = "OrbotVPN"; private ParcelFileDescriptor mInterface;
- private int mSocksProxyPort = 9999; + //private Thread mThreadProxy; + //private int mSocksProxyPort = 9999; // private ProxyServer mProxyServer;
private final static int VPN_MTU = 1500; @@ -63,7 +63,7 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { // Stop the previous session by interrupting the thread. if (mThreadVPN == null || (!mThreadVPN.isAlive())) { - startSocksBypass (); + enableAppRouting (); setupTun2Socks(); }
@@ -71,8 +71,19 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { return START_STICKY; }
- private void startSocksBypass () + private void enableAppRouting () { + + boolean isLollipop = false; + + if (isLollipop) + { + //allow for specific apps to be sent through VPN based on list selection + } + else + { + //do socks bypass trick + } }
@Override diff --git a/src/org/torproject/android/wizard/ChooseLocaleWizardActivity.java b/src/org/torproject/android/wizard/ChooseLocaleWizardActivity.java deleted file mode 100644 index 1a620c1..0000000 --- a/src/org/torproject/android/wizard/ChooseLocaleWizardActivity.java +++ /dev/null @@ -1,136 +0,0 @@ -package org.torproject.android.wizard; - -import java.util.Locale; - -import org.torproject.android.R; -import org.torproject.android.TorConstants; -import org.torproject.android.service.TorServiceUtils; - -import android.app.Activity; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.content.res.Configuration; -import android.os.Bundle; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.Toast; - -public class ChooseLocaleWizardActivity extends Activity implements TorConstants { - - private int flag = 0; - private ListView listLocales; - - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - } - - @Override - protected void onStart() { - - super.onStart(); - setContentView(R.layout.layout_wizard_locale); - - - listLocales = (ListView)findViewById(R.id.wizard_locale_list); - Button next = ((Button)findViewById(R.id.btnWizard2)); - // next.setEnabled(false); - - String[] strLangs = getResources().getStringArray(R.array.languages); - strLangs[0] = Locale.getDefault().getDisplayName(); - ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1, strLangs); - listLocales.setAdapter(adapter); - - listLocales.setSelection(0); - - - listLocales.setOnItemClickListener(new OnItemClickListener() { - - - @Override - public void onItemClick(AdapterView<?> arg0, View arg1, - int arg2, long arg3) { - - setLocalePref(arg2); - finish(); - startActivity(new Intent(ChooseLocaleWizardActivity.this, LotsaText.class)); - - } - }); - - next.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - setLocalePref(0); - finish(); - startActivity(new Intent(ChooseLocaleWizardActivity.this, LotsaText.class)); - - } - }); - - - - } - - private void setLocalePref(int selId) - { - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - Configuration config = getResources().getConfiguration(); - - String[] localeVals = getResources().getStringArray(R.array.languages_values); - - String lang = localeVals[selId]; - - Editor pEdit = prefs.edit(); - pEdit.putString(PREF_DEFAULT_LOCALE, lang); - pEdit.commit(); - Locale locale = null; - - if (lang.equals("xx")) - { - locale = Locale.getDefault(); - - } - else - locale = new Locale(lang); - - Locale.setDefault(locale); - config.locale = locale; - getResources().updateConfiguration(config, getResources().getDisplayMetrics()); - - - - - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - - } - - //Code to override the back button! - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if(keyCode == KeyEvent.KEYCODE_BACK){ - Toast.makeText(getApplicationContext(), R.string.wizard_exit_at_first_screen_toast, Toast.LENGTH_SHORT).show(); - return true; - } - return false; - } -} \ No newline at end of file diff --git a/src/org/torproject/android/wizard/LotsaText.java b/src/org/torproject/android/wizard/LotsaText.java deleted file mode 100644 index 137282f..0000000 --- a/src/org/torproject/android/wizard/LotsaText.java +++ /dev/null @@ -1,137 +0,0 @@ -package org.torproject.android.wizard; - -import org.torproject.android.R; -import org.torproject.android.TorConstants; -import org.torproject.android.service.TorServiceUtils; - -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.view.KeyEvent; -import android.view.View; -import android.widget.Button; -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 = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - boolean wizardScreen1 = prefs.getBoolean("wizardscreen1",true); - if(wizardScreen1) - stepOne(); - else - stepTwo(); - - } - - @Override - protected void onResume() { - super.onResume(); - - - } - - private void stepOne() { - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - 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); - - setTitle(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)); - - btn1.setVisibility(Button.INVISIBLE); - - btn2.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - stepTwo(); - } - }); - - } - - private void stepTwo() { - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - 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); - - setTitle(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)); - - btn1.setVisibility(Button.VISIBLE); - - - btn1.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - - stepOne(); - } - }); - - btn2.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - finish(); - startActivity(new Intent(LotsaText.this, TipsAndTricks.class)); - } - }); - - } - - //Code to override the back button! - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if(keyCode == KeyEvent.KEYCODE_BACK){ - finish(); - startActivity(new Intent(getBaseContext(), ChooseLocaleWizardActivity.class)); - return true; - } - return true; - } - -} \ No newline at end of file diff --git a/src/org/torproject/android/wizard/TipsAndTricks.java b/src/org/torproject/android/wizard/TipsAndTricks.java deleted file mode 100644 index 3eea373..0000000 --- a/src/org/torproject/android/wizard/TipsAndTricks.java +++ /dev/null @@ -1,248 +0,0 @@ -package org.torproject.android.wizard; - -import org.torproject.android.Orbot; -import org.torproject.android.R; -import org.torproject.android.TorConstants; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.TextView; - -public class TipsAndTricks extends Activity implements TorConstants { - - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - } - - @Override - protected void onStart() { - - super.onStart(); - setContentView(R.layout.layout_wizard_tips); - - stepFive(); - - } - - @Override - protected void onResume() { - super.onResume(); - - - } - - void stepFive(){ - - - String title = getString(R.string.wizard_tips_title); - - setTitle(title); - - Button btnLink = (Button)findViewById(R.id.WizardRootButtonInstallGibberbot); - - btnLink.setOnClickListener(new OnClickListener() { - - public void onClick(View view) { - - String url = getString(R.string.gibberbot_apk_url); - finish(); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - - } - }); - - btnLink = (Button)findViewById(R.id.WizardRootButtonInstallOrweb); - - btnLink.setOnClickListener(new OnClickListener() { - - public void onClick(View view) { - - String url = getString(R.string.orweb_apk_url); - finish(); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - - } - }); - - btnLink = (Button)findViewById(R.id.WizardRootButtonInstallDuckgo); - - btnLink.setOnClickListener(new OnClickListener() { - - public void onClick(View view) { - - String url = getString(R.string.duckgo_apk_url); - finish(); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - - } - }); - - btnLink = (Button)findViewById(R.id.WizardRootButtonInstallFirefox); - - btnLink.setOnClickListener(new OnClickListener() { - - public void onClick(View view) { - - String url = getString(R.string.proxymob_setup_url); - finish(); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - - } - }); - - btnLink = (Button)findViewById(R.id.WizardRootButtonInstallTwitter); - - btnLink.setOnClickListener(new OnClickListener() { - - public void onClick(View view) { - - String url = getString(R.string.twitter_setup_url); - finish(); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - - } - }); - - btnLink = (Button)findViewById(R.id.WizardRootButtonInstallStoryMaker); - - btnLink.setOnClickListener(new OnClickListener() { - - public void onClick(View view) { - - String url = getString(R.string.story_maker_url); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - - } - }); - - btnLink = (Button)findViewById(R.id.WizardRootButtonInstallMartus); - - btnLink.setOnClickListener(new OnClickListener() { - - public void onClick(View view) { - - String url = getString(R.string.martus_url); - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); - - } - }); - - - btnLink = (Button)findViewById(R.id.WizardRootButtonGooglePlay); - - btnLink.setOnClickListener(new OnClickListener() { - - public void onClick(View view) { - - String url = getString(R.string.wizard_tips_play_url); - 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() { - - public void onClick(View v) { - finish(); - startActivityForResult(new Intent(TipsAndTricks.this, LotsaText.class), 1); - } - }); - - next.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - showWizardFinal(); - } - }); - - } - - private void showWizardFinal () - { - setContentView(R.layout.scrollingtext_buttons_view); - String title = getString(R.string.wizard_final); - String msg = getString(R.string.wizard_final_msg); - - setTitle(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)); - - btn2.setText(getString(R.string.btn_finish)); - btn1.setVisibility(Button.VISIBLE); - - btn1.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - finish(); - startActivity(new Intent(TipsAndTricks.this, LotsaText.class)); - } - }); - - btn2.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - finish(); - } - }); - } - - //Code to override the back button! - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if(keyCode == KeyEvent.KEYCODE_BACK){ - finish(); - startActivity(new Intent(getBaseContext(), LotsaText.class)); - return true; - } - return false; - } - - /* - 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