many fixes include landscape view, invalid settings handling and cleanup of shell cmd code

svn:r21829
This commit is contained in:
Nathan Freitas 2010-03-06 14:56:39 +00:00
parent 33b6b2c23c
commit 24f6adc201
8 changed files with 214 additions and 133 deletions

View File

@ -16,10 +16,11 @@
<string name="status_shutting_down">Orbot is shutting down</string>
<string name="tor_process_connecting">Starting Tor...</string>
<string name="tor_process_connecting_step2">authenticating...</string>
<string name="tor_process_connecting_step2">authenticating control connection...</string>
<string name="tor_process_connecting_step3">complete.</string>
<string name="tor_process_connecting_step4">waiting.</string>
<string name="not_anonymous_yet">WARNING: Your traffic is not anonymous yet! Please configure your applications to use HTTP proxy 127.0.0.1:8118 or SOCKS5 proxy 127.0.0.1:9050</string>
<string name="menu_home">Home</string>
<string name="menu_browse">Browse</string>
<string name="menu_settings">Settings</string>
@ -36,9 +37,9 @@
Please visit https://www.torproject.org/docs/android.html for the latest information.
\n\n
For non-rooted Android 1.x devices (G1, MyTouch3G, Hero): Please use the "ProxySurf" browser available in the Android Market, and set
the HTTP Proxy to 127.0.0.1 and port 8118. For Instant Messsaging, try "Beem" in the market, and set the SOCKS5 proxy to 127.0.0.1 / port 9050.
the HTTP Proxy to 127.0.0.1 and port 8118, for HTTP traffic only (HTTP/S will not work). For Instant Messsaging, try "Beem" in the market, and set the SOCKS5 proxy to 127.0.0.1 / port 9050.
\n\n
For Android 2.x devices, you MUST ROOT your device in order for Orbot to work transparently for all web and DNS traffic. Otherwise, the "Beem" app will allow
For Android 2.x devices, you MUST ROOT your device in order for Orbot to work transparently, as there is no browser that will work for non-root devices. Otherwise, the "Beem" app will allow
you to set the SOCKS5 proxy to 127.0.0.1 and port 9050. You should also enable SSL to protect your username and password.
\n\n
If you root your device, whether it is 1.x or 2.x based, Orbot will automatically, transparently proxy all web traffic (http and https)

View File

@ -1,13 +1,24 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceScreen android:title="Bridges">
<PreferenceCategory android:title="Transparent Proxying">
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_transparent"
android:title="Transparent Proxying"
android:summary="Root Devices Only: Per App Torification"
android:enabled="true"/>
</PreferenceCategory>
<PreferenceCategory android:title="Bridges">
<CheckBoxPreference android:defaultValue="false"
android:title="Use Bridges" android:key="pref_bridges_enabled"
android:summary="Enable alternate entrance nodes into the Tor Network"></CheckBoxPreference>
<CheckBoxPreference android:defaultValue="false"
android:title="Update Bridges from Authority" android:key="pref_bridges_update"
android:title="Update from Authority" android:key="pref_bridges_update"
android:summary="Modify bridge list automatically"></CheckBoxPreference>
<EditTextPreference android:key="pref_bridge_list"
@ -15,17 +26,11 @@ android:title="Bridges"
android:summary="IP address and port of bridges"
android:dialogTitle="Enter Bridge Addresses"
/>
</PreferenceScreen>
</PreferenceCategory>
<CheckBoxPreference
android:defaultValue="false"
android:key="pref_transparent"
android:title="Transparent Proxying"
android:summary="ROOTED DEVICES ONLY: Activate Tor for all web traffic and DNS"
android:enabled="true"/>
<PreferenceScreen android:title="Relays">
<PreferenceCategory android:title="Relays">
<CheckBoxPreference android:key="pref_or"
android:defaultValue="false"
android:title="Relaying"
@ -48,7 +53,7 @@ android:summary="The nickname for your Tor relay"
android:dialogTitle="Enter a custom relay nickname"
/>
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory android:title="ReachableAddresses">
<CheckBoxPreference
@ -56,7 +61,7 @@ android:key="pref_reachable_addresses"
android:defaultValue="false"
android:title="ReachableAddresses"
android:summary="Run as a client behind a firewall with restrictive policies"
android:enabled="false"></CheckBoxPreference>
android:enabled="true"></CheckBoxPreference>
<EditTextPreference
android:key="pref_reachable_addresses_ports"

View File

@ -190,6 +190,25 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
}
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putString("log", logBuffer.toString());
// etc.
super.onSaveInstanceState(savedInstanceState);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
String logText = savedInstanceState.getString("log");
logBuffer.append(logText);
}
/* (non-Javadoc)
* @see android.app.Activity#onResume()
*/
@ -427,8 +446,6 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
}
/*
* Load the basic settings application to display torrc
@ -482,6 +499,16 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
if (useBridges)
{
if (bridgeList == null || bridgeList.length() == 0)
{
showAlert("In order to use the bridge feature, you must enter at least one bridge IP address." +
"Send an email to bridges@torproject.org with the line \"get bridges\" by itself in the body of the mail from a gmail account.");
showSettings();
return;
}
torrcText.append("UseBridges 1");
torrcText.append('\n');
@ -530,8 +557,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
}
catch (Exception e)
{
Toast.makeText(this,"Your ReachableAddresses settings caused an exception!",
Toast.LENGTH_LONG).show();
showAlert("Your ReachableAddresses settings caused an exception!");
}
try
@ -555,13 +581,19 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
}
catch (Exception e)
{
Toast.makeText(this,"Your relay settings caused an exception!", Toast.LENGTH_LONG).show();
showAlert("Your relay settings caused an exception!");
showSettings();
return;
}
Utils.saveTextFile(TorServiceConstants.TORRC_INSTALL_PATH, torrcText.toString());
}
private void showAlert(String msg)
{
Toast.makeText(this,msg,
Toast.LENGTH_LONG).show();
}
/*
* Set the state of the running/not running graphic and label
*/
@ -589,10 +621,15 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
progressDialog.cancel();
progressDialog.hide();
progressDialog = null;
if (!enableTransparentProxy)
{
showAlert(getString(R.string.not_anonymous_yet));
}
}
if (torServiceMsg != null && torServiceMsg.length()>0)
Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
// if (torServiceMsg != null && torServiceMsg.length()>0)
// Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
}
@ -623,6 +660,7 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
String pComp = torServiceMsg.substring(idx-2,idx).trim();
int ipComp = Integer.parseInt(pComp);
progressDialog.setProgress(ipComp);
}
}
@ -631,8 +669,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
imgStatus.setImageResource(R.drawable.torstopping);
lblStatus.setText(getString(R.string.status_shutting_down));
if (torServiceMsg != null && torServiceMsg.length()>0)
Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
//if (torServiceMsg != null && torServiceMsg.length()>0)
//Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
@ -640,8 +678,8 @@ public class Orbot extends Activity implements OnClickListener, TorConstants, On
else
{
if (torServiceMsg != null && torServiceMsg.length()>0)
Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
//if (torServiceMsg != null && torServiceMsg.length()>0)
//Toast.makeText(this, torServiceMsg, Toast.LENGTH_LONG).show();
if (progressDialog != null)

View File

@ -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 notice stdout\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/data\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";

View File

@ -6,7 +6,9 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import net.freehaven.tor.control.ConfigEntry;
@ -277,6 +279,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable
conn = null;
}
StringBuilder log = new StringBuilder();
int procId = TorServiceUtils.findProcessId(TorServiceConstants.TOR_BINARY_INSTALL_PATH);
@ -285,7 +288,8 @@ public class TorService extends Service implements TorServiceConstants, Runnable
Log.i(TAG,"Found Tor PID=" + procId + " - killing now...");
TorServiceUtils.doCommand(SHELL_CMD_KILL, procId + "");
String[] cmd = { SHELL_CMD_KILL + ' ' + procId + "" };
TorServiceUtils.doShellCommand(cmd,log, false, false);
procId = TorServiceUtils.findProcessId(TorServiceConstants.TOR_BINARY_INSTALL_PATH);
}
@ -296,8 +300,9 @@ public class TorService extends Service implements TorServiceConstants, Runnable
{
Log.i(TAG,"Found Privoxy PID=" + procId + " - killing now...");
TorServiceUtils.doCommand(SHELL_CMD_KILL, procId + "");
String[] cmd = { SHELL_CMD_KILL + ' ' + procId + "" };
TorServiceUtils.doShellCommand(cmd,log, false, false);
procId = TorServiceUtils.findProcessId(TorServiceConstants.PRIVOXY_INSTALL_PATH);
}
@ -346,12 +351,15 @@ public class TorService extends Service implements TorServiceConstants, Runnable
}
StringBuilder log = new StringBuilder ();
Log.i(TAG,"Setting permission on Tor binary");
TorServiceUtils.doCommand(SHELL_CMD_CHMOD, CHMOD_EXE_VALUE + ' ' + TOR_BINARY_INSTALL_PATH);
String[] cmd1 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + TOR_BINARY_INSTALL_PATH};
TorServiceUtils.doShellCommand(cmd1, log, false, true);
Log.i(TAG,"Setting permission on Privoxy binary");
TorServiceUtils.doCommand(SHELL_CMD_CHMOD, CHMOD_EXE_VALUE + ' ' + PRIVOXY_INSTALL_PATH);
String[] cmd2 = {SHELL_CMD_CHMOD + ' ' + CHMOD_EXE_VALUE + ' ' + PRIVOXY_INSTALL_PATH};
TorServiceUtils.doShellCommand(cmd2, log, false, true);
return true;
}
@ -368,41 +376,82 @@ public class TorService extends Service implements TorServiceConstants, Runnable
checkTorBinaries ();
Log.i(TAG,"Starting tor process");
TorServiceUtils.doCommand(TOR_BINARY_INSTALL_PATH, TOR_COMMAND_LINE_ARGS);
int procId = TorServiceUtils.findProcessId(TorServiceConstants.TOR_BINARY_INSTALL_PATH);
while (procId == -1)
new Thread()
{
TorServiceUtils.doCommand(TOR_BINARY_INSTALL_PATH, TOR_COMMAND_LINE_ARGS);
procId = TorServiceUtils.findProcessId(TorServiceConstants.TOR_BINARY_INSTALL_PATH);
if (procId == -1)
public void run ()
{
this.sendCallbackMessage("Couldn't start Tor process... retrying...");
Thread.sleep(3000);
try {
runPrivoxyShellCmd();
} catch (Exception e) {
Log.w(TAG,"Error starting Privoxy",e);
}
}
}
}.start();
Log.i(TAG,"Tor process id=" + procId);
new Thread()
{
public void run ()
{
try {
runTorShellCmd();
} catch (Exception e) {
Log.w(TAG,"Error starting Tor",e);
}
}
}.start();
showToolbarNotification("Orbot starting...", "Orbot is starting up", R.drawable.tornotification);
initControlConnection ();
}
private void runTorShellCmd() throws Exception
{
StringBuilder log = new StringBuilder();
Log.i(TAG,"Starting tor process");
String[] torCmd = {TOR_BINARY_INSTALL_PATH + ' ' + TOR_COMMAND_LINE_ARGS};
TorServiceUtils.doShellCommand(torCmd, log, false, false);
Thread.sleep(1000);
int procId = TorServiceUtils.findProcessId(TorServiceConstants.TOR_BINARY_INSTALL_PATH);
while (procId == -1)
{
log = new StringBuilder();
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);
}
}
Log.i(TAG,"Tor process id=" + procId);
showToolbarNotification("Orbot starting...", "Orbot is starting up", R.drawable.tornotification);
initControlConnection ();
}
private void runPrivoxyShellCmd () throws Exception
{
int privoxyProcId = TorServiceUtils.findProcessId(TorServiceConstants.PRIVOXY_INSTALL_PATH);
StringBuilder log = new StringBuilder();
while (privoxyProcId == -1)
{
TorServiceUtils.doCommand(PRIVOXY_INSTALL_PATH, PRIVOXY_COMMAND_LINE_ARGS);
String[] cmds =
{ PRIVOXY_INSTALL_PATH + " " + PRIVOXY_COMMAND_LINE_ARGS };
TorServiceUtils.doShellCommand(cmds, log, false, true);
privoxyProcId = TorServiceUtils.findProcessId(TorServiceConstants.PRIVOXY_INSTALL_PATH);
if (privoxyProcId == -1)
{
this.sendCallbackMessage("Couldn't start Privoxy process... retrying...");
this.sendCallbackMessage("Couldn't start Privoxy process... retrying...\n" + log);
Thread.sleep(3000);
}
}
@ -705,19 +754,40 @@ public class TorService extends Service implements TorServiceConstants, Runnable
};
private void sendCallbackMessage (String status)
private ArrayList<String> callbackBuffer = new ArrayList<String>();
private void sendCallbackMessage (String newStatus)
{
// Broadcast to all clients the new value.
final int N = mCallbacks.beginBroadcast();
for (int i=0; i<N; i++) {
try {
mCallbacks.getBroadcastItem(i).statusChanged(status);
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
callbackBuffer.add(newStatus);
if (N > 0)
{
Iterator<String> it = callbackBuffer.iterator();
String status = null;
while (it.hasNext())
{
status = it.next();
for (int i=0; i<N; i++) {
try {
mCallbacks.getBroadcastItem(i).statusChanged(status);
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
}
}
callbackBuffer.clear();
}
mCallbacks.finishBroadcast();
}
}

View File

@ -19,7 +19,7 @@ public interface TorServiceConstants {
public final static String TORRC_INSTALL_PATH = TOR_HOME + TORRC_ASSET_KEY; //path to install torrc to within the android app data folder
public final static String TORRC_ZIP_KEY = "assets/" + TORRC_ASSET_KEY; //key of the torrc file in the Zip file
//how to launch tor
public final static String TOR_COMMAND_LINE_ARGS = "-f " + TORRC_INSTALL_PATH;
public final static String TOR_COMMAND_LINE_ARGS = "-f " + TORRC_INSTALL_PATH + " || exit\n";
//privoxy
public final static String PRIVOXY_ASSET_KEY = "privoxy";
@ -32,7 +32,7 @@ public interface TorServiceConstants {
public final static String PRIVOXYCONFIG_ZIP_KEY = "assets/" + PRIVOXYCONFIG_ASSET_KEY; //key of the privoxy file in the Zip file
//how to launch privoxy
public final static String PRIVOXY_COMMAND_LINE_ARGS = ' ' + PRIVOXYCONFIG_INSTALL_PATH;
public final static String PRIVOXY_COMMAND_LINE_ARGS = ' ' + PRIVOXYCONFIG_INSTALL_PATH + " || exit\n";
//where to send the notices log
public final static String TOR_LOG_PATH = TOR_HOME + "notices.log";

View File

@ -112,6 +112,8 @@ public class TorServiceUtils implements TorServiceConstants {
public static int findProcessId(String command)
{
Log.i(TAG, "finding process id for: " + command);
int procId = -1;
Runtime r = Runtime.getRuntime();
@ -147,60 +149,19 @@ public class TorServiceUtils implements TorServiceConstants {
}
public static Process doCommand(String command, String arg1)
{
Log.i(TAG,"executing command: " + command + ' ' + arg1);
Runtime r = Runtime.getRuntime();
Process proc = null;
StringBuilder log = new StringBuilder();
try {
proc = r.exec(command + ' ' + arg1);
/*
final char buf[] = new char[1024];
// Consume the "stdout"
InputStreamReader reader = new InputStreamReader(proc.getInputStream());
int read=0;
while ((read=reader.read(buf)) != -1) {
if (log != null) log.append(buf, 0, read);
}
// Consume the "stderr"
reader = new InputStreamReader(proc.getErrorStream());
read=0;
while ((read=reader.read(buf)) != -1) {
if (log != null) log.append(buf, 0, read);
}*/
Log.i(TAG,"command process exit value: " + proc.exitValue());
Log.i(TAG, "shell cmd output: " + log.toString());
} catch (Exception e) {
Log.e(TAG, "error: " + e.getMessage());
Log.e(TAG, "shell cmd output: " + log.toString());
}
return proc;
}
public static boolean hasRoot ()
{
String[] cmds = {"exit 0"};
int code = doRootCommand(cmds,null);
int code = doShellCommand(cmds,null,true, true);
return (code == 0);
}
public static int doRootCommand(String[] cmds, StringBuilder log)
public static int doShellCommand(String[] cmds, StringBuilder log, boolean isRoot, boolean waitFor)
{
Log.i(TAG,"executing commands: " + cmds.length);
Log.i(TAG,"executing shell cmds: " + cmds[0] + "; isRoot=" + isRoot);
Process proc = null;
@ -208,9 +169,12 @@ public class TorServiceUtils implements TorServiceConstants {
try {
proc = Runtime.getRuntime().exec("su");
OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream());
if (isRoot)
proc = Runtime.getRuntime().exec("su");
else
proc = Runtime.getRuntime().exec("sh");
OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream());
for (int i = 0; i < cmds.length; i++)
{
@ -221,25 +185,28 @@ public class TorServiceUtils implements TorServiceConstants {
out.flush();
out.write("exit\n");
out.flush();
/*
final char buf[] = new char[1024];
// Consume the "stdout"
InputStreamReader reader = new InputStreamReader(proc.getInputStream());
int read=0;
while ((read=reader.read(buf)) != -1) {
if (log != null) log.append(buf, 0, read);
if (waitFor)
{
exitCode = proc.waitFor();
final char buf[] = new char[10];
// Consume the "stdout"
InputStreamReader reader = new InputStreamReader(proc.getInputStream());
int read=0;
while ((read=reader.read(buf)) != -1) {
if (log != null) log.append(buf, 0, read);
}
// Consume the "stderr"
reader = new InputStreamReader(proc.getErrorStream());
read=0;
while ((read=reader.read(buf)) != -1) {
if (log != null) log.append(buf, 0, read);
}
Log.i(TAG,"command process exit value: " + exitCode);
}
// Consume the "stderr"
reader = new InputStreamReader(proc.getErrorStream());
read=0;
while ((read=reader.read(buf)) != -1) {
if (log != null) log.append(buf, 0, read);
}*/
exitCode = proc.waitFor();
Log.i(TAG,"command process exit value: " + exitCode);
} catch (Exception e) {
Log.e(TAG, "Error executing shell cmd: " + e.getMessage(),e);

View File

@ -34,7 +34,7 @@ public class TorTransProxy {
try {
// Run an empty script just to check root access
String[] cmd = {"exit 0"};
if (TorServiceUtils.doRootCommand(cmd, null) == 0) {
if (TorServiceUtils.doShellCommand(cmd, null, true, true) == 0) {
hasRoot = true;
return true;
}
@ -53,7 +53,7 @@ public class TorTransProxy {
String[] cmds = {CMD_DNS_PROXYING_ADD};
code = TorServiceUtils.doRootCommand(cmds, log);
code = TorServiceUtils.doShellCommand(cmds, log, true, true);
return code;
@ -64,7 +64,7 @@ public class TorTransProxy {
StringBuilder res = new StringBuilder();
try {
String[] cmds = {CMD_NAT_FLUSH};
int code = TorServiceUtils.doRootCommand(cmds, res);
int code = TorServiceUtils.doShellCommand(cmds, res, true, true);
if (code != 0) {
Log.w(TAG, "error purging iptables. exit code: " + code + "\n" + res);
return false;
@ -110,7 +110,7 @@ public class TorTransProxy {
String[] cmd = {script.toString()};
code = TorServiceUtils.doRootCommand(cmd, res);
code = TorServiceUtils.doShellCommand(cmd, res, true, true);
String msg = res.toString();
Log.e(TAG, msg);