diff --git a/Orbot/.classpath b/Orbot/.classpath index 888751ae..20af842e 100644 --- a/Orbot/.classpath +++ b/Orbot/.classpath @@ -3,7 +3,7 @@ - + diff --git a/Orbot/AndroidManifest.xml b/Orbot/AndroidManifest.xml index 5798a852..9350d086 100644 --- a/Orbot/AndroidManifest.xml +++ b/Orbot/AndroidManifest.xml @@ -4,11 +4,11 @@ android:versionName="0.2.2.13-orbot-alpha-0.0.8" android:versionCode="2"> + - - + @@ -22,10 +22,10 @@ - - - - + + + + @@ -33,8 +33,17 @@ + + + + + + + + diff --git a/Orbot/BUILD b/Orbot/BUILD index cb75aaf8..7f09c55b 100644 --- a/Orbot/BUILD +++ b/Orbot/BUILD @@ -1,4 +1,4 @@ -This document explains how to properly build an Android package of Orbot from +nThis document explains how to properly build an Android package of Orbot from source. It covers building on Debian Lenny (5.0.3). Please install the following prerequisites (instructions for each follows): diff --git a/Orbot/build.xml b/Orbot/build.xml index 0128a2de..08dd4a6c 100644 --- a/Orbot/build.xml +++ b/Orbot/build.xml @@ -1,5 +1,5 @@ - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Orbot/res/xml/preferences.xml b/Orbot/res/xml/preferences.xml index 55974d05..99c0cd26 100644 --- a/Orbot/res/xml/preferences.xml +++ b/Orbot/res/xml/preferences.xml @@ -1,14 +1,30 @@ - + + + + + + + diff --git a/Orbot/src/org/torproject/android/Orbot.java b/Orbot/src/org/torproject/android/Orbot.java index 74c3da4d..f5160afc 100644 --- a/Orbot/src/org/torproject/android/Orbot.java +++ b/Orbot/src/org/torproject/android/Orbot.java @@ -15,6 +15,7 @@ import org.torproject.android.service.TorServiceConstants; import android.app.Activity; import android.app.AlertDialog; +import android.app.NotificationManager; import android.app.ProgressDialog; import android.content.ComponentName; import android.content.Context; @@ -87,31 +88,25 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On MenuItem mItem = null; - mItemOnOff = menu.add(0, 1, Menu.NONE, getString(R.string.menu_start)); mItemOnOff.setIcon(android.R.drawable.ic_menu_share); + mItemOnOff.setAlphabeticShortcut('t'); mItem = menu.add(0, 4, Menu.NONE, getString(R.string.menu_settings)); mItem.setIcon(R.drawable.ic_menu_register); - - mItem = menu.add(0, 5, Menu.NONE, getString(R.string.menu_apps)); - mItem.setIcon(R.drawable.ic_menu_goto); - - if (!TorServiceUtils.hasRoot()) - { - mItem.setEnabled(false); - - } - + mItem = menu.add(0, 7, Menu.NONE, getString(R.string.menu_verify)); + mItem.setIcon(R.drawable.ic_menu_goto); + mItem = menu.add(0,6, Menu.NONE, getString(R.string.menu_log)); mItem.setIcon(R.drawable.ic_menu_reports); mItem = menu.add(0, 3, Menu.NONE, getString(R.string.menu_info)); mItem.setIcon(R.drawable.ic_menu_about); - - + mItem = menu.add(0, 8, Menu.NONE, getString(R.string.menu_exit)); + mItem.setIcon(R.drawable.ic_menu_exit); + return true; } @@ -172,10 +167,41 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On { showApps(); } + else if (item.getItemId() == 7) + { + //launch check.torproject.org + openBrowser(URL_TOR_CHECK); + } + else if (item.getItemId() == 8) + { + //exit app + doExit(); + + + } return true; } + private void doExit () + { + try { + stopTor(); + + NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + mNotificationManager.cancelAll(); + + unbindService(); + + + } catch (RemoteException e) { + Log.w(TAG, e); + } + + finish(); + + } + /* Return to the main view when the back key is pressed * (non-Javadoc) * @see android.app.Activity#onKeyDown(int, android.view.KeyEvent) @@ -231,6 +257,10 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On protected void onResume() { super.onResume(); + NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + mNotificationManager.cancelAll(); + updateStatus (""); //update the status, which checks the service status if (showingSettings) @@ -352,6 +382,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On entry = (ListEntry) convertView.getTag(); } final TorifiedApp app = apps[position]; + + entry.text.setText(app.getName()); final CheckBox box = entry.box; box.setTag(app); @@ -432,7 +464,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On new AlertDialog.Builder(this) .setTitle(getString(R.string.menu_info)) .setMessage(msg.toString()) - .setView(view) .setNeutralButton(getString(R.string.button_about), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { @@ -466,6 +497,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On setContentView(currentView); txtMessageLog = (TextView)findViewById(R.id.messageLog); + + txtMessageLog.setClickable(true); txtMessageLog.setText(logBuffer.toString()); } @@ -633,6 +666,12 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On if (mService != null) torStatus = mService.getStatus(); + if (this.currentView == R.layout.layout_log) + { + txtMessageLog.append(torServiceMsg); + txtMessageLog.append("\n"); + + } if (imgStatus != null) { @@ -755,6 +794,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On mHandler.sendMessage(msg); updateStatus(""); + } /* @@ -857,6 +897,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On logBuffer.append(torServiceMsg); logBuffer.append('\n'); + + if (torServiceMsg.length() > 0 && torServiceMsg.charAt(0)!='>') updateStatus(torServiceMsg); break; diff --git a/Orbot/src/org/torproject/android/SettingsPreferences.java b/Orbot/src/org/torproject/android/SettingsPreferences.java index a61c5d9d..d7d407bc 100644 --- a/Orbot/src/org/torproject/android/SettingsPreferences.java +++ b/Orbot/src/org/torproject/android/SettingsPreferences.java @@ -5,21 +5,53 @@ package org.torproject.android; import org.torproject.android.service.TorServiceUtils; +import android.content.Intent; import android.os.Bundle; +import android.preference.CheckBoxPreference; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceActivity; -import android.util.Log; +import android.preference.PreferenceCategory; + public class SettingsPreferences - extends PreferenceActivity { + extends PreferenceActivity implements OnPreferenceClickListener { + private CheckBoxPreference prefCBTransProxy = null; + private CheckBoxPreference prefcBTransProxyAll = null; + private Preference prefTransProxyApps = null; + protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); + if (!TorServiceUtils.hasRoot()) + { getPreferenceScreen().getPreference(0).setEnabled(false); + } + else + { + prefCBTransProxy = ((CheckBoxPreference)((PreferenceCategory)this.getPreferenceScreen().getPreference(0)).getPreference(0)); + prefcBTransProxyAll = (CheckBoxPreference)((PreferenceCategory)this.getPreferenceScreen().getPreference(0)).getPreference(1); + prefTransProxyApps = ((PreferenceCategory)this.getPreferenceScreen().getPreference(0)).getPreference(2); + + prefcBTransProxyAll.setEnabled(prefCBTransProxy.isChecked()); + + prefTransProxyApps.setEnabled(prefCBTransProxy.isChecked() && (!prefcBTransProxyAll.isChecked())); + + prefCBTransProxy.setOnPreferenceClickListener(this); + prefcBTransProxyAll.setOnPreferenceClickListener(this); + prefTransProxyApps.setOnPreferenceClickListener(this); + + } + + } + + + /* (non-Javadoc) * @see android.app.Activity#onStop() */ @@ -27,7 +59,27 @@ public class SettingsPreferences protected void onStop() { super.onStop(); - Log.i(getClass().getName(),"Exiting Preferences"); + //Log.i(getClass().getName(),"Exiting Preferences"); } + @Override + public boolean onPreferenceClick(Preference preference) { + + + if (preference == prefTransProxyApps) + { + startActivity(new Intent(this, AppManager.class)); + } + else + { + prefcBTransProxyAll.setEnabled(prefCBTransProxy.isChecked()); + prefTransProxyApps.setEnabled(prefCBTransProxy.isChecked() && (!prefcBTransProxyAll.isChecked())); + + } + + return true; + } + + + } diff --git a/Orbot/src/org/torproject/android/TorConstants.java b/Orbot/src/org/torproject/android/TorConstants.java index 73d9622b..6d389073 100644 --- a/Orbot/src/org/torproject/android/TorConstants.java +++ b/Orbot/src/org/torproject/android/TorConstants.java @@ -24,7 +24,7 @@ public interface TorConstants { public final static String NEWLINE = "\n"; public final static String TORRC_DEFAULT = - "SocksPort 9050\nSocksListenAddress 127.0.0.1\nSafeSocks 1\nDNSPort 5400\nLog debug syslog\nDataDirectory /data/data/org.torproject.android/data\n" + "SocksPort 9050\nSocksListenAddress 127.0.0.1\nSafeSocks 1\nDNSPort 5400\nLog debug syslog\nDataDirectory /data/data/org.torproject.android/cache\n" + "ControlPort 9051\nCookieAuthentication 1\nRelayBandwidthRate 20 KBytes\nRelayBandwidthBurst 20 KBytes\nAutomapHostsOnResolve 1\nTransPort 9040\n"; public final static String INTENT_TOR_SERVICE = "org.torproject.android.service.TOR_SERVICE"; diff --git a/Orbot/src/org/torproject/android/TorifiedApp.java b/Orbot/src/org/torproject/android/TorifiedApp.java index 1ba8afe3..9e659e75 100644 --- a/Orbot/src/org/torproject/android/TorifiedApp.java +++ b/Orbot/src/org/torproject/android/TorifiedApp.java @@ -1,5 +1,7 @@ package org.torproject.android; +import android.graphics.drawable.Drawable; + public class TorifiedApp { private boolean enabled; @@ -7,6 +9,7 @@ public class TorifiedApp { private String username; private String procname; private String name; + private Drawable icon; private boolean torified = false; @@ -97,4 +100,12 @@ public class TorifiedApp { this.name = name; } + + public Drawable getIcon() { + return icon; + } + + public void setIcon(Drawable icon) { + this.icon = icon; + } } diff --git a/Orbot/src/org/torproject/android/service/TorService.java b/Orbot/src/org/torproject/android/service/TorService.java index 21fab12f..2341acee 100644 --- a/Orbot/src/org/torproject/android/service/TorService.java +++ b/Orbot/src/org/torproject/android/service/TorService.java @@ -42,6 +42,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable private static final int NOTIFY_ID = 1; + private static final int MAX_START_TRIES = 3; + /** Called when the activity is first created. */ public void onCreate() { @@ -114,6 +116,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable Log.i(TAG, "onUnbind Called: " + intent.getAction()); + return super.onUnbind(intent); @@ -169,20 +172,6 @@ public class TorService extends Service implements TorServiceConstants, Runnable public void onStart(Intent intent, int startId) { super.onStart(intent, startId); - /* - if (currentStatus == STATUS_ON && conn != null && webProxy != null) - { - //we are good to go - Log.i(TAG,"onStart: Tor is running"); - - } - else - { - Log.i(TAG,"onStart: Starting up Tor"); - - new Thread(this).start(); - } - */ } public void run () @@ -323,6 +312,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable { Log.i(TAG, msg); + + sendCallbackMessage('>' + msg); } @@ -386,14 +377,20 @@ public class TorService extends Service implements TorServiceConstants, Runnable checkTorBinaries (); + + new Thread() { public void run () { try { - runPrivoxyShellCmd(); + runPrivoxyShellCmd(); + } catch (Exception e) { - Log.w(TAG,"Error starting Privoxy",e); + currentStatus = STATUS_OFF; + Log.i(TAG,"Unable to start Privoxy: " + e.getMessage(),e); + sendCallbackMessage("Unable to start Privoxy: " + e.getMessage()); + } } }.start(); @@ -403,10 +400,13 @@ public class TorService extends Service implements TorServiceConstants, Runnable public void run () { try { - runTorShellCmd(); + runTorShellCmd(); + } catch (Exception e) { - Log.w(TAG,"Error starting Tor",e); - } + Log.i(TAG,"Unable to start Tor: " + e.getMessage(),e); + sendCallbackMessage("Unable to start Tor: " + e.getMessage()); + stopTor(); + } } }.start(); @@ -425,54 +425,82 @@ public class TorService extends Service implements TorServiceConstants, Runnable Thread.sleep(1000); int procId = TorServiceUtils.findProcessId(TorServiceConstants.TOR_BINARY_INSTALL_PATH); - while (procId == -1) + int attempts = 0; + + while (procId == -1 && attempts < MAX_START_TRIES) { log = new StringBuilder(); - + + logNotice(torCmd[0]); + TorServiceUtils.doShellCommand(torCmd, log, false, false); procId = TorServiceUtils.findProcessId(TorServiceConstants.TOR_BINARY_INSTALL_PATH); if (procId == -1) { - this.sendCallbackMessage("Couldn't start Tor process...\n" + log.toString()); - Thread.sleep(5000); + sendCallbackMessage("Couldn't start Tor process...\n" + log.toString()); + Thread.sleep(1000); + sendCallbackMessage("Trying to start Tor again...\n" + log.toString()); + Thread.sleep(3000); + attempts++; } + + logNotice(log.toString()); } - Log.i(TAG,"Tor process id=" + procId); + if (procId == -1) + { + throw new Exception ("Unable to start Tor"); + } + else + { - showToolbarNotification("Orbot starting...", "Orbot is starting up", R.drawable.tornotification); - - initControlConnection (); + logNotice("Tor process id=" + procId); + + showToolbarNotification("Orbot starting...", "Tor is running", R.drawable.tornotification); + + initControlConnection (); + } } private void runPrivoxyShellCmd () throws Exception { int privoxyProcId = TorServiceUtils.findProcessId(TorServiceConstants.PRIVOXY_INSTALL_PATH); - StringBuilder log = new StringBuilder(); + StringBuilder log = null; - while (privoxyProcId == -1) + int attempts = 0; + + while (privoxyProcId == -1 && attempts < MAX_START_TRIES) { + log = new StringBuilder(); + String[] cmds = { PRIVOXY_INSTALL_PATH + " " + PRIVOXY_COMMAND_LINE_ARGS }; + + logNotice (cmds[0]); + TorServiceUtils.doShellCommand(cmds, log, false, true); + + //wait one second to make sure it has started up Thread.sleep(1000); privoxyProcId = TorServiceUtils.findProcessId(TorServiceConstants.PRIVOXY_INSTALL_PATH); - if (privoxyProcId == -1) { this.sendCallbackMessage("Couldn't start Privoxy process... retrying...\n" + log); Thread.sleep(3000); + attempts++; } + + logNotice(log.toString()); } sendCallbackMessage("Privoxy is running on port: " + PORT_HTTP); Thread.sleep(100); - Log.i(TAG,"Privoxy process id=" + privoxyProcId); + logNotice("Privoxy process id=" + privoxyProcId); @@ -668,21 +696,16 @@ public class TorService extends Service implements TorServiceConstants, Runnable public void message(String severity, String msg) { - Log.i(TAG, "[Tor Control Port] " + severity + ": " + msg); - - if (msg.indexOf(TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)!=-1) - { - currentStatus = STATUS_ON; - showToolbarNotification ("Orbot","Anonymous browsing is enabled",R.drawable.tornotification); - - } - else - { - showToolbarNotification("Orbot", msg, R.drawable.tornotification); - - } - - sendCallbackMessage (msg); + Log.i(TAG, "[Tor Control Port] " + severity + ": " + msg); + + if (msg.indexOf(TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)!=-1) + { + currentStatus = STATUS_ON; + showToolbarNotification ("Orbot","Tor is enabled",R.drawable.tornotification); + + } + + sendCallbackMessage (msg); } @@ -694,31 +717,72 @@ public class TorService extends Service implements TorServiceConstants, Runnable public void orConnStatus(String status, String orName) { - Log.i(TAG,"OrConnStatus=" + status + ": " + orName); - - + StringBuilder sb = new StringBuilder(); + sb.append("orConnStatus ("); + sb.append((orName) ); + sb.append("): "); + sb.append(status); + + logNotice(sb.toString()); } public void streamStatus(String status, String streamID, String target) { - Log.i(TAG,"StreamStatus=" + status + ": " + streamID); + + StringBuilder sb = new StringBuilder(); + sb.append("StreamStatus ("); + sb.append((streamID)); + sb.append("): "); + sb.append(status); + + logNotice(sb.toString()); + } public void unrecognized(String type, String msg) { - Log.i(TAG,"unrecognized log=" + type + ": " + msg); + + StringBuilder sb = new StringBuilder(); + sb.append("Message ("); + sb.append(type); + sb.append("): "); + sb.append(msg); + + logNotice(sb.toString()); + } public void bandwidthUsed(long read, long written) { + sendCallbackMessage ("bandwidth used: read=" + read + " written=" + written); + StringBuilder sb = new StringBuilder(); + sb.append("Bandwidth used: "); + sb.append(read/1000); + sb.append("kb read / "); + sb.append(written/1000); + sb.append("kb written"); + + logNotice(sb.toString()); + } public void circuitStatus(String status, String circID, String path) { - - } + + StringBuilder sb = new StringBuilder(); + sb.append("Circuit ("); + sb.append((circID)); + sb.append("): "); + sb.append(status); + sb.append("; "); + sb.append(path); + + logNotice(sb.toString()); + + } + public IBinder onBind(Intent intent) { // Select the interface to return. If your service only implements // a single interface, you can just return it here without checking @@ -786,6 +850,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable for (int i=0; i