[or-cvs] r21761: {projects} added transproxy app chooser view (in projects/android/trunk/Orbot/src/org/torproject/android: . service)
Nathan Freitas
nathan at freitas.net
Sat Feb 27 23:56:47 UTC 2010
Author: n8fr8
Date: 2010-02-27 23:56:46 +0000 (Sat, 27 Feb 2010)
New Revision: 21761
Added:
projects/android/trunk/Orbot/src/org/torproject/android/TorifiedApp.java
projects/android/trunk/Orbot/src/org/torproject/android/service/TorTransProxy.java
Removed:
projects/android/trunk/Orbot/src/org/torproject/android/service/TorRoot.java
Modified:
projects/android/trunk/Orbot/src/org/torproject/android/Orbot.java
projects/android/trunk/Orbot/src/org/torproject/android/SettingsPreferences.java
projects/android/trunk/Orbot/src/org/torproject/android/TorConstants.java
projects/android/trunk/Orbot/src/org/torproject/android/service/TorService.java
projects/android/trunk/Orbot/src/org/torproject/android/service/TorServiceConstants.java
projects/android/trunk/Orbot/src/org/torproject/android/service/TorServiceUtils.java
Log:
added transproxy app chooser view
Modified: projects/android/trunk/Orbot/src/org/torproject/android/Orbot.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/Orbot.java 2010-02-27 01:21:22 UTC (rev 21760)
+++ projects/android/trunk/Orbot/src/org/torproject/android/Orbot.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -3,11 +3,14 @@
package org.torproject.android;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.StringTokenizer;
import org.torproject.android.service.ITorService;
import org.torproject.android.service.ITorServiceCallback;
-import org.torproject.android.service.TorRoot;
+import org.torproject.android.service.TorServiceUtils;
+import org.torproject.android.service.TorTransProxy;
import org.torproject.android.service.TorServiceConstants;
import android.app.Activity;
@@ -32,12 +35,19 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewGroup;
import android.view.View.OnClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
+import android.widget.CompoundButton.OnCheckedChangeListener;
-public class Orbot extends Activity implements OnClickListener, TorConstants
+public class Orbot extends Activity implements OnClickListener, TorConstants, OnCheckedChangeListener
{
/* Useful UI bits */
@@ -45,18 +55,17 @@
private TextView lblStatus = null; //the main text display widget
private ImageView imgStatus = null; //the main touchable image for activating Orbot
private ProgressDialog progressDialog;
+ private ListView listApps;
+ private boolean showingSettings = false;
/* Some tracking bits */
- private int torStatus = STATUS_REQUIRES_DEMAND; //latest status reported from the tor service
+ private int torStatus = STATUS_READY; //latest status reported from the tor service
private int currentView = 0; //the currently displayed UI view
private StringBuffer logBuffer = new StringBuffer(); //the output of the service log messages
- private String lastUrl = null;
/* Tor Service interaction */
/* The primary interface we will be calling on the service. */
ITorService mService = null;
-
-
/** Called when the activity is first created. */
@Override
@@ -83,15 +92,22 @@
mItem = menu.add(0, 2, Menu.NONE, getString(R.string.menu_browse));
mItem.setIcon(R.drawable.ic_menu_goto);
+
+ mItem = menu.add(0, 3, Menu.NONE, getString(R.string.menu_info));
+ mItem.setIcon(R.drawable.ic_menu_about);
- mItem = menu.add(0, 3, Menu.NONE, getString(R.string.menu_settings));
+ 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_register);
+
+ if (!TorServiceUtils.hasRoot())
+ mItem.setEnabled(false);
- mItem = menu.add(0, 4, Menu.NONE, getString(R.string.menu_log));
+ mItem = menu.add(0,6, Menu.NONE, getString(R.string.menu_log));
mItem.setIcon(R.drawable.ic_menu_reports);
- mItem = menu.add(0, 5, Menu.NONE, getString(R.string.menu_info));
- mItem.setIcon(R.drawable.ic_menu_about);
return true;
}
@@ -109,11 +125,11 @@
{
this.showMain();
}
- else if (item.getItemId() == 3)
+ else if (item.getItemId() == 4)
{
this.showSettings();
}
- else if (item.getItemId() == 4)
+ else if (item.getItemId() == 6)
{
this.showMessageLog();
}
@@ -121,10 +137,14 @@
{
openBrowser(URL_TOR_CHECK);
}
- else if (item.getItemId() == 5)
+ else if (item.getItemId() == 3)
{
showHelp();
}
+ else if (item.getItemId() == 5)
+ {
+ showApps();
+ }
return true;
}
@@ -158,11 +178,9 @@
protected void onPause() {
super.onPause();
+
}
-
-
-
/* (non-Javadoc)
* @see android.app.Activity#onResume()
*/
@@ -171,6 +189,17 @@
super.onResume();
updateStatus (""); //update the status, which checks the service status
+
+ if (showingSettings)
+ {
+
+ showingSettings = false;
+ processSettings();
+
+ }
+
+
+
}
/* (non-Javadoc)
@@ -198,6 +227,8 @@
protected void onStop() {
super.onStop();
+ TorServiceUtils.saveAppSettings(this);
+
unbindService();
}
@@ -210,6 +241,24 @@
{
bindService(); //connect the UI activity to the remote service
+ if (currentView == R.layout.layout_apps)
+ {
+ if (hasRoot)
+ {
+
+ TorServiceUtils.saveAppSettings(this);
+
+ if (enableTransparentProxy)
+ {
+ TorTransProxy.purgeNatIptables();
+ TorTransProxy.setDNSProxying();
+ TorTransProxy.setTransparentProxying(this, TorServiceUtils.getApps(this));
+ }
+
+
+ }
+ }
+
currentView = R.layout.layout_main;
setContentView(currentView);
@@ -232,6 +281,67 @@
}
+ private void loadApps ()
+ {
+ final TorifiedApp[] apps = TorServiceUtils.getApps(this);
+
+ Arrays.sort(apps, new Comparator<TorifiedApp>() {
+ @Override
+ public int compare(TorifiedApp o1, TorifiedApp o2) {
+ if (o1.isTorified() == o2.isTorified()) return o1.getName().compareTo(o2.getName());
+ if (o1.isTorified()) return -1;
+ return 1;
+ }
+ });
+
+ final LayoutInflater inflater = getLayoutInflater();
+
+ final ListAdapter adapter = new ArrayAdapter<TorifiedApp>(this,R.layout.layout_apps_item,R.id.itemtext,apps) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ListEntry entry;
+ if (convertView == null) {
+ // Inflate a new view
+ convertView = inflater.inflate(R.layout.layout_apps_item, parent, false);
+ entry = new ListEntry();
+ entry.box = (CheckBox) convertView.findViewById(R.id.itemcheck);
+ entry.text = (TextView) convertView.findViewById(R.id.itemtext);
+ convertView.setTag(entry);
+ entry.box.setOnCheckedChangeListener(Orbot.this);
+ } else {
+ // Convert an existing view
+ entry = (ListEntry) convertView.getTag();
+ }
+ final TorifiedApp app = apps[position];
+ entry.text.setText(app.getName());
+ final CheckBox box = entry.box;
+ box.setTag(app);
+ box.setChecked(app.isTorified());
+ return convertView;
+ }
+ };
+ this.listApps.setAdapter(adapter);
+
+ }
+
+ /**
+ * Called an application is check/unchecked
+ */
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ final TorifiedApp app = (TorifiedApp) buttonView.getTag();
+ if (app != null) {
+ app.setTorified(isChecked);
+ }
+
+ TorServiceUtils.saveAppSettings(this);
+
+ }
+
+ private static class ListEntry {
+ private CheckBox box;
+ private TextView text;
+ }
/*
* Show the about view - a popup dialog
*/
@@ -285,7 +395,16 @@
.show();
}
+ private void showApps ()
+ {
+ currentView = R.layout.layout_apps;
+ setContentView(currentView);
+ listApps = (ListView)findViewById(R.id.applistview);
+
+ loadApps();
+
+ }
/*
* Show the message log UI
*/
@@ -308,6 +427,7 @@
private void showSettings ()
{
+ showingSettings = true;
startActivity(new Intent(this, SettingsPreferences.class));
@@ -331,6 +451,19 @@
enableTransparentProxy = prefs.getBoolean(PREF_TRANSPARENT, false);
+ if (hasRoot)
+ {
+ if (enableTransparentProxy)
+ {
+ TorTransProxy.setDNSProxying();
+ TorTransProxy.setTransparentProxying(this, TorServiceUtils.getApps(this));
+ }
+ else
+ {
+ TorTransProxy.purgeNatIptables();
+ }
+
+ }
String bridgeList = prefs.getString(PREF_BRIDGES_LIST,"");
if (useBridges)
@@ -436,7 +569,7 @@
}
}
- else if (torStatus == STATUS_UNAVAILABLE)
+ else if (torStatus == STATUS_OFF)
{
imgStatus.setImageResource(R.drawable.torstopping);
lblStatus.setText(getString(R.string.status_shutting_down));
@@ -493,15 +626,16 @@
{
}
- else if (mService.getStatus() == STATUS_REQUIRES_DEMAND)
+ else if (mService.getStatus() == STATUS_READY)
{
processSettings();
mService.setProfile(PROFILE_ON);
if (hasRoot && enableTransparentProxy)
{
- TorRoot.enableDNSProxying();
- TorRoot.enabledWebProxying();
+
+ TorTransProxy.setDNSProxying();
+ TorTransProxy.setTransparentProxying(this,TorServiceUtils.getApps(this));
}
}
else
@@ -511,7 +645,9 @@
if (hasRoot && enableTransparentProxy)
{
- TorRoot.purgeNatIptables();
+ TorTransProxy.purgeNatIptables();
+ //TorRoot.setDNSProxying(false);
+ //TorRoot.setTransparentProxying(this,false);
}
}
}
@@ -617,7 +753,7 @@
mIsBound = true;
- hasRoot = TorRoot.hasRootAccess();
+ hasRoot = TorTransProxy.hasRootAccess();
}
Modified: projects/android/trunk/Orbot/src/org/torproject/android/SettingsPreferences.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/SettingsPreferences.java 2010-02-27 01:21:22 UTC (rev 21760)
+++ projects/android/trunk/Orbot/src/org/torproject/android/SettingsPreferences.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -5,6 +5,7 @@
import android.os.Bundle;
import android.preference.PreferenceActivity;
+import android.util.Log;
public class SettingsPreferences
extends PreferenceActivity {
@@ -13,4 +14,15 @@
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
+
+ /* (non-Javadoc)
+ * @see android.app.Activity#onStop()
+ */
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ Log.i(getClass().getName(),"Exiting Preferences");
+ }
+
}
Modified: projects/android/trunk/Orbot/src/org/torproject/android/TorConstants.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/TorConstants.java 2010-02-27 01:21:22 UTC (rev 21760)
+++ projects/android/trunk/Orbot/src/org/torproject/android/TorConstants.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -12,8 +12,8 @@
//path to check Tor against
public final static String URL_TOR_CHECK = "https://check.torproject.org";
- public final static int STATUS_UNAVAILABLE = -1;
- public final static int STATUS_REQUIRES_DEMAND = 0;
+ public final static int STATUS_OFF = -1;
+ public final static int STATUS_READY = 0;
public final static int STATUS_ON = 1;
public final static int STATUS_CONNECTING = 2;
Added: projects/android/trunk/Orbot/src/org/torproject/android/TorifiedApp.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/TorifiedApp.java (rev 0)
+++ projects/android/trunk/Orbot/src/org/torproject/android/TorifiedApp.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -0,0 +1,100 @@
+package org.torproject.android;
+
+public class TorifiedApp {
+
+ private boolean enabled;
+ private int uid;
+ private String username;
+ private String procname;
+ private String name;
+
+ private boolean torified = false;
+
+ /**
+ * @return the torified
+ */
+ public boolean isTorified() {
+ return torified;
+ }
+ /**
+ * @param torified the torified to set
+ */
+ public void setTorified(boolean torified) {
+ this.torified = torified;
+ }
+ private int[] enabledPorts;
+
+ /**
+ * @return the enabledPorts
+ */
+ public int[] getEnabledPorts() {
+ return enabledPorts;
+ }
+ /**
+ * @param enabledPorts the enabledPorts to set
+ */
+ public void setEnabledPorts(int[] enabledPorts) {
+ this.enabledPorts = enabledPorts;
+ }
+ /**
+ * @return the enabled
+ */
+ public boolean isEnabled() {
+ return enabled;
+ }
+ /**
+ * @param enabled the enabled to set
+ */
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+ /**
+ * @return the uid
+ */
+ public int getUid() {
+ return uid;
+ }
+ /**
+ * @param uid the uid to set
+ */
+ public void setUid(int uid) {
+ this.uid = uid;
+ }
+ /**
+ * @return the username
+ */
+ public String getUsername() {
+ return username;
+ }
+ /**
+ * @param username the username to set
+ */
+ public void setUsername(String username) {
+ this.username = username;
+ }
+ /**
+ * @return the procname
+ */
+ public String getProcname() {
+ return procname;
+ }
+ /**
+ * @param procname the procname to set
+ */
+ public void setProcname(String procname) {
+ this.procname = procname;
+ }
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
Deleted: projects/android/trunk/Orbot/src/org/torproject/android/service/TorRoot.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/service/TorRoot.java 2010-02-27 01:21:22 UTC (rev 21760)
+++ projects/android/trunk/Orbot/src/org/torproject/android/service/TorRoot.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -1,259 +0,0 @@
-/* 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.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.util.Iterator;
-import java.util.List;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.util.Log;
-
-/**
- * Contains shared programming interfaces.
- * All iptables "communication" is handled by this class.
- */
-public final class TorRoot {
- private final static String TAG = "TOR_ROOT";
-
- // Do we have root access?
- private static boolean hasroot = false;
-
- private final static String CMD_NAT_FLUSH = "iptables -t nat -F || exit\n";
- private final static String CMD_NAT_IPTABLES_80 = "iptables -t nat -A OUTPUT -p tcp --dport 80 -j DNAT --to 127.0.0.1:8118 || exit\n";
- private final static String CMD_NAT_IPTABLES_443 = "iptables -t nat -A OUTPUT -p tcp --dport 443 -j DNAT --to 127.0.0.1:9040 || exit\n";
-
- private final static String CMD_DNS_PROXYING = "iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to 127.0.0.1:5400 || exit\n";
-
- public static boolean enableDNSProxying ()
- {
-
- final StringBuilder script = new StringBuilder();
- int code;
-
- //Enable UDP Proxying
- script.append(CMD_DNS_PROXYING);
- StringBuilder res = new StringBuilder();
-
- try
- {
- code = runScriptAsRoot(script.toString(), res);
-
- if (code != 0)
- {
- Log.w(TAG, "error apply DNS proxying: " + res.toString());
-
- }
- } catch (Exception e) {
- Log.w(TAG, "error apply DNS proxying: " + res.toString(), e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Purge and re-add all rules (internal implementation).
- * @param ctx application context (mandatory)
- * @param uids list of selected uids to allow or disallow (depending on the working mode)
- * @param showErrors indicates if errors should be alerted
- */
- public static boolean enabledWebProxying() {
-
- final StringBuilder script = new StringBuilder();
- try {
- int code;
-
- script.append(CMD_NAT_IPTABLES_80);
- script.append(CMD_NAT_IPTABLES_443);
- /*
- int uid = android.os.Process.getUidForName("dhcp");
- if (uid != -1) script.append("iptables -A OUTPUT " + itfFilter + " -m owner --uid-owner " + uid + " -j ACCEPT || exit\n");
- uid = android.os.Process.getUidForName("wifi");
- if (uid != -1) script.append("iptables -A OUTPUT " + itfFilter + " -m owner --uid-owner " + uid + " -j ACCEPT || exit\n");
- */
-
- StringBuilder res = new StringBuilder();
- code = runScriptAsRoot(script.toString(), res);
-
- String msg = res.toString();
- Log.e(TAG, msg);
-
- } catch (Exception e) {
- Log.w(TAG, "error refreshing iptables: " + e);
- }
- return false;
- }
-
-
- /**
- * Purge all iptables rules.
- * @return true if the rules were purged
- */
- public static boolean purgeNatIptables() {
- StringBuilder res = new StringBuilder();
- try {
- int code = runScriptAsRoot(CMD_NAT_FLUSH, res);
- if (code != 0) {
- Log.w(TAG, "error purging iptables. exit code: " + code + "\n" + res);
- return false;
- }
- return true;
- } catch (Exception e) {
- Log.w(TAG,"error purging iptables: " + e);
- return false;
- }
- }
-
-
- /**
- * Check if we have root access
- * @return boolean true if we have root
- */
- public static boolean hasRootAccess() {
- if (hasroot) return true;
- try {
- // Run an empty script just to check root access
- if (runScriptAsRoot("exit 0", null, 20000) == 0) {
- hasroot = true;
- return true;
- }
- } catch (Exception e) {
- }
- Log.w(TAG, "Could not acquire root access.");
- return false;
- }
-
- /**
- * Runs a script as root (multiple commands separated by "\n").
- *
- * @param script the script to be executed
- * @param res the script output response (stdout + stderr)
- * @param timeout timeout in milliseconds (-1 for none)
- * @return the script exit code
- */
- public static int runScriptAsRoot(String script, StringBuilder res, final long timeout) {
- Log.i(TAG,"executing script: " + script);
- final ScriptRunner runner = new ScriptRunner(script, res);
- runner.start();
- try {
- if (timeout > 0) {
- runner.join(timeout);
- } else {
- runner.join();
- }
- if (runner.isAlive()) {
- // Timed-out
- runner.interrupt();
- runner.destroy();
- runner.join(50);
- }
- } catch (InterruptedException ex) {}
- return runner.exitcode;
- }
-
- /**
- * Runs a script as root (multiple commands separated by "\n") with a default timeout of 5 seconds.
- *
- * @param script the script to be executed
- * @param res the script output response (stdout + stderr)
- * @param timeout timeout in milliseconds (-1 for none)
- * @return the script exit code
- * @throws IOException on any error executing the script, or writing it to disk
- */
- public static int runScriptAsRoot(String script, StringBuilder res) throws IOException {
- return runScriptAsRoot(script, res, 5000);
- }
-
- /**
- * Internal thread used to execute scripts as root.
- */
- private static final class ScriptRunner extends Thread {
- private final String script;
- private final StringBuilder res;
- public int exitcode = -1;
- private Process exec;
-
- /**
- * Creates a new script runner.
- * @param script script to run
- * @param res response output
- */
- public ScriptRunner(String script, StringBuilder res) {
- this.script = script;
- this.res = res;
- }
- @Override
- public void run() {
- try {
- // Create the "su" request to run the command
- // note that this will create a shell that we must interact to (using stdin/stdout)
- exec = Runtime.getRuntime().exec("su");
- final OutputStreamWriter out = new OutputStreamWriter(exec.getOutputStream());
- // Write the script to be executed
- out.write(script);
- // Ensure that the last character is an "enter"
- if (!script.endsWith("\n")) out.write("\n");
- out.flush();
- // Terminate the "su" process
- out.write("exit\n");
- out.flush();
- final char buf[] = new char[1024];
- // Consume the "stdout"
- InputStreamReader r = new InputStreamReader(exec.getInputStream());
- int read=0;
- while ((read=r.read(buf)) != -1) {
- if (res != null) res.append(buf, 0, read);
- }
- // Consume the "stderr"
- r = new InputStreamReader(exec.getErrorStream());
- read=0;
- while ((read=r.read(buf)) != -1) {
- if (res != null) res.append(buf, 0, read);
- }
- // get the process exit code
- if (exec != null) this.exitcode = exec.waitFor();
- } catch (InterruptedException ex) {
- if (res != null) res.append("\nOperation timed-out");
- } catch (Exception ex) {
- if (res != null) res.append("\n" + ex);
- } finally {
- destroy();
- }
- }
- /**
- * Destroy this script runner
- */
- public synchronized void destroy() {
- if (exec != null) exec.destroy();
- exec = null;
- }
- }
-
- public void getApps (Context context)
- {
- PackageManager pMgr = context.getPackageManager();
-
- List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
-
- Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
-
- ApplicationInfo aInfo = null;
-
- while (itAppInfo.hasNext())
- {
- aInfo = itAppInfo.next();
-
- boolean appEnabled = aInfo.enabled;
- int uid = aInfo.uid; //-m owner --uid-owner
- String username = pMgr.getNameForUid(uid);
- String procName = aInfo.processName;
- String name = aInfo.name;
-
- }
- }
-}
Modified: projects/android/trunk/Orbot/src/org/torproject/android/service/TorService.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/service/TorService.java 2010-02-27 01:21:22 UTC (rev 21760)
+++ projects/android/trunk/Orbot/src/org/torproject/android/service/TorService.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -32,7 +32,7 @@
- private static int currentStatus = STATUS_REQUIRES_DEMAND;
+ private static int currentStatus = STATUS_READY;
private TorControlConnection conn = null;
@@ -80,12 +80,12 @@
} catch (RuntimeException e) {
Log.i(TAG,"Unable to connect to existing Tor instance,",e);
- currentStatus = STATUS_REQUIRES_DEMAND;
+ currentStatus = STATUS_OFF;
this.stopTor();
} catch (Exception e) {
Log.i(TAG,"Unable to connect to existing Tor instance,",e);
- currentStatus = STATUS_REQUIRES_DEMAND;
+ currentStatus = STATUS_OFF;
this.stopTor();
}
@@ -203,7 +203,7 @@
}
catch (Exception e)
{
- currentStatus = STATUS_REQUIRES_DEMAND;
+ currentStatus = STATUS_OFF;
this.showToolbarNotification("Orbot", "Unable to start Tor", R.drawable.tornotification);
Log.i(TAG,"Unable to start Tor: " + e.getMessage(),e);
}
@@ -226,14 +226,14 @@
private void stopTor ()
{
- currentStatus = STATUS_UNAVAILABLE;
+ currentStatus = STATUS_OFF;
sendCallbackMessage("Web proxy shutdown");
killTorProcess ();
- currentStatus = STATUS_REQUIRES_DEMAND;
+ currentStatus = STATUS_READY;
showToolbarNotification ("Orbot","Anonymous browsing is disabled",R.drawable.tornotificationoff);
sendCallbackMessage("Anonymous browsing is disabled");
@@ -591,7 +591,7 @@
}
else
{
- currentStatus = STATUS_UNAVAILABLE;
+ currentStatus = STATUS_OFF;
sendCallbackMessage ("shutting down...");
_torInstance.stopTor();
Modified: projects/android/trunk/Orbot/src/org/torproject/android/service/TorServiceConstants.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/service/TorServiceConstants.java 2010-02-27 01:21:22 UTC (rev 21760)
+++ projects/android/trunk/Orbot/src/org/torproject/android/service/TorServiceConstants.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -76,12 +76,11 @@
//control port
public final static String TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE = "Bootstrapped 100%";
- public final static int STATUS_UNAVAILABLE = -1;
- public final static int STATUS_REQUIRES_DEMAND = 0;
+ public final static int STATUS_OFF = -1;
+ public final static int STATUS_READY = 0;
public final static int STATUS_ON = 1;
public final static int STATUS_CONNECTING = 2;
public final static int PROFILE_OFF = -1;
- public final static int PROFILE_ONDEMAND = 0;
public final static int PROFILE_ON = 1;
}
Modified: projects/android/trunk/Orbot/src/org/torproject/android/service/TorServiceUtils.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/service/TorServiceUtils.java 2010-02-27 01:21:22 UTC (rev 21760)
+++ projects/android/trunk/Orbot/src/org/torproject/android/service/TorServiceUtils.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -5,13 +5,110 @@
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
import java.util.StringTokenizer;
+import org.torproject.android.TorifiedApp;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.util.Log;
public class TorServiceUtils implements TorServiceConstants {
+ private static TorifiedApp[] apps = null;
+ private final static String PREFS_KEY = "OrbotPrefs";
+ private final static String PREFS_KEY_TORIFIED = "PrefTord";
+
+ public static void saveAppSettings (Context context)
+ {
+ if (apps == null)
+ return;
+
+ final SharedPreferences prefs = context.getSharedPreferences(PREFS_KEY, 0);
+
+ StringBuilder tordApps = new StringBuilder();
+
+ for (int i = 0; i < apps.length; i++)
+ {
+ if (apps[i].isTorified())
+ {
+ tordApps.append(apps[i].getUsername());
+ tordApps.append("|");
+ }
+ }
+
+ Editor edit = prefs.edit();
+ edit.putString(PREFS_KEY_TORIFIED, tordApps.toString());
+ edit.commit();
+
+ }
+
+ public static TorifiedApp[] getApps (Context context)
+ {
+ if (apps != null)
+ return apps;
+
+ final SharedPreferences prefs = context.getSharedPreferences(PREFS_KEY, 0);
+
+ String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, "");
+ String[] tordApps;
+
+ StringTokenizer st = new StringTokenizer(tordAppString,"|");
+ tordApps = new String[st.countTokens()];
+ int tordIdx = 0;
+ while (st.hasMoreTokens())
+ {
+ tordApps[tordIdx++] = st.nextToken();
+ }
+
+ Arrays.sort(tordApps);
+
+ //else load the apps up
+ PackageManager pMgr = context.getPackageManager();
+
+ List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
+
+ Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
+
+ apps = new TorifiedApp[lAppInfo.size()];
+
+ ApplicationInfo aInfo = null;
+
+ int appIdx = 0;
+
+ while (itAppInfo.hasNext())
+ {
+ aInfo = itAppInfo.next();
+ apps[appIdx] = new TorifiedApp();
+
+ apps[appIdx].setEnabled(aInfo.enabled);
+ apps[appIdx].setUid(aInfo.uid);
+ apps[appIdx].setUsername(pMgr.getNameForUid(apps[appIdx].getUid()));
+ apps[appIdx].setProcname(aInfo.processName);
+ apps[appIdx].setName(pMgr.getApplicationLabel(aInfo).toString());
+
+ // check if this application is allowed
+ if (Arrays.binarySearch(tordApps, apps[appIdx].getUsername()) >= 0) {
+ apps[appIdx].setTorified(true);
+ }
+ else
+ {
+ apps[appIdx].setTorified(false);
+ }
+
+ appIdx++;
+ }
+
+ return apps;
+ }
+
public static int findProcessId(String command)
{
int procId = -1;
@@ -104,18 +201,17 @@
{
Log.i(TAG,"executing commands: " + cmds.length);
- Runtime runtime = Runtime.getRuntime();
-
+
Process proc = null;
int exitCode = -1;
try {
- proc = runtime.exec(cmds[0]);
-
+ proc = Runtime.getRuntime().exec("su");
+
OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream());
- for (int i = 1; i < cmds.length; i++)
+ for (int i = 0; i < cmds.length; i++)
{
out.write(cmds[i]);
out.write("\n");
@@ -123,7 +219,8 @@
out.flush();
out.write("exit\n");
-
+ out.flush();
+ /*
final char buf[] = new char[1024];
// Consume the "stdout"
InputStreamReader reader = new InputStreamReader(proc.getInputStream());
@@ -136,7 +233,7 @@
read=0;
while ((read=reader.read(buf)) != -1) {
if (log != null) log.append(buf, 0, read);
- }
+ }*/
exitCode = proc.waitFor();
Added: projects/android/trunk/Orbot/src/org/torproject/android/service/TorTransProxy.java
===================================================================
--- projects/android/trunk/Orbot/src/org/torproject/android/service/TorTransProxy.java (rev 0)
+++ projects/android/trunk/Orbot/src/org/torproject/android/service/TorTransProxy.java 2010-02-27 23:56:46 UTC (rev 21761)
@@ -0,0 +1,124 @@
+package org.torproject.android.service;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.torproject.android.TorifiedApp;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.util.Log;
+
+public class TorTransProxy {
+
+ private final static String TAG = "TorTransProxy";
+
+ private final static String CMD_NAT_FLUSH = "iptables -t nat -F || exit\n";
+// private final static String CMD_NAT_IPTABLES_ALL = "iptables -t nat -A OUTPUT -j DNAT --to 127.0.0.1:9040 || exit\n";
+
+ private final static String CMD_DNS_PROXYING_ADD = "iptables -t nat -A PREROUTING -p udp --dport 53 -j DNAT --to 127.0.0.1:5400 || exit\n";
+ private final static String CMD_DNS_PROXYING_DELETE = "iptables -t nat -D PREROUTING -p udp --dport 53 -j DNAT --to 127.0.0.1:5400 || exit\n";
+
+ private final static String IPTABLES_ADD = " -A ";
+ private final static String IPTABLES_DELETE = " -D ";
+
+ private static boolean hasRoot = false;
+
+ /**
+ * Check if we have root access
+ * @return boolean true if we have root
+ */
+ public static boolean hasRootAccess() {
+ if (hasRoot) return true;
+ try {
+ // Run an empty script just to check root access
+ String[] cmd = {"exit 0"};
+ if (TorServiceUtils.doRootCommand(cmd, null) == 0) {
+ hasRoot = true;
+ return true;
+ }
+ } catch (Exception e) {
+ }
+ Log.w(TAG, "Could not acquire root access.");
+ return false;
+ }
+
+ public static int setDNSProxying ()
+ {
+
+ final StringBuilder log = new StringBuilder();
+ int code;
+
+ String[] cmds = {CMD_DNS_PROXYING_ADD};
+
+
+ code = TorServiceUtils.doRootCommand(cmds, log);
+
+ return code;
+
+
+ }
+
+ public static boolean purgeNatIptables() {
+ StringBuilder res = new StringBuilder();
+ try {
+ String[] cmds = {CMD_NAT_FLUSH};
+ int code = TorServiceUtils.doRootCommand(cmds, res);
+ if (code != 0) {
+ Log.w(TAG, "error purging iptables. exit code: " + code + "\n" + res);
+ return false;
+ }
+ return true;
+ } catch (Exception e) {
+ Log.w(TAG,"error purging iptables: " + e);
+ return false;
+ }
+ }
+
+ public static boolean setTransparentProxying(Context context, TorifiedApp[] apps) {
+
+ String command = null;
+
+ command = IPTABLES_ADD; //ADD
+
+ final StringBuilder script = new StringBuilder();
+
+ try {
+ int code;
+
+ for (int i = 0; i < apps.length; i++)
+ {
+
+ if (apps[i].getUsername().startsWith("org.torproject.android")) //we never want to Tor this!
+ continue;
+
+ if (apps[i].isTorified())
+ {
+ Log.i(TAG,"enabling transproxy for app: " + apps[i].getUsername() + "(" + apps[i].getUid() + ")");
+
+ script.append("iptables -t nat");
+ script.append(command);
+ script.append("OUTPUT -p tcp -m owner --uid-owner ");
+ script.append(apps[i].getUid());
+ script.append(" -j DNAT --to 127.0.0.1:9040");
+ script.append(" || exit\n");
+ }
+ }
+
+ StringBuilder res = new StringBuilder();
+
+ String[] cmd = {script.toString()};
+
+ code = TorServiceUtils.doRootCommand(cmd, res);
+
+ String msg = res.toString();
+ Log.e(TAG, msg);
+
+ } catch (Exception e) {
+ Log.w(TAG, "error refreshing iptables: " + e);
+ }
+ return false;
+ }
+
+}
More information about the tor-commits
mailing list